diff options
296 files changed, 8558 insertions, 2364 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt index 4b36c44a5f..cf10ecccfb 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -600,6 +600,7 @@ Tharax Ferraris Thickbrick Sleaford VWR-7109 VWR-9287 + VWR-13483 VWR-13947 Thraxis Epsilon SVC-371 diff --git a/indra/develop.py b/indra/develop.py index 05ad12f20e..eaecdd0ab6 100755 --- a/indra/develop.py +++ b/indra/develop.py @@ -573,7 +573,7 @@ class WindowsSetup(PlatformSetup): if self.gens[self.generator]['ver'] in [ r'8.0', r'9.0' ]: config = '\"%s|Win32\"' % config - return "buildconsole %s.sln /build %s" % (self.project_name, config) + return "buildconsole %(prj)s.sln /build /cfg=%(cfg)s" % {'prj': self.project_name, 'cfg': config} # devenv.com is CLI friendly, devenv.exe... not so much. return ('"%sdevenv.com" %s.sln /build %s' % diff --git a/indra/llaudio/llstreamingaudio_fmod.cpp b/indra/llaudio/llstreamingaudio_fmod.cpp index a71a87203c..a4620fa13c 100644 --- a/indra/llaudio/llstreamingaudio_fmod.cpp +++ b/indra/llaudio/llstreamingaudio_fmod.cpp @@ -174,7 +174,7 @@ void LLStreamingAudio_FMOD::update() break; case -3: // failed to open, file not found, perhaps - llwarns << "InternetSteam - failed to open" << llendl; + llwarns << "InternetStream - failed to open" << llendl; stop(); return; case -4: diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index c8c4fe0c3c..1e625bcee8 100644 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h @@ -139,6 +139,9 @@ public: /// Get information about a specific Callable LLSD getMetadata(const std::string& name) const; + /// Retrieve the LLSD key we use for one-arg <tt>operator()</tt> method + std::string getDispatchKey() const { return mKey; } + private: template <class CLASS, typename METHOD> void addMethod(const std::string& name, const std::string& desc, diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 45b84ea3ea..f5c90291b8 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -36,6 +36,7 @@ #include "llinstancetracker.h" #define FAST_TIMER_ON 1 +#define TIME_FAST_TIMERS 0 #if LL_WINDOWS @@ -56,7 +57,7 @@ inline U32 get_cpu_clock_count_32() return ret_val; } -// return full timer value, still shifted by 8 bits +// return full timer value, *not* shifted by 8 bits inline U64 get_cpu_clock_count_64() { U64 ret_val; @@ -69,7 +70,7 @@ inline U64 get_cpu_clock_count_64() mov dword ptr [ret_val+4], edx mov dword ptr [ret_val], eax } - return ret_val >> 8; + return ret_val; } #endif // LL_WINDOWS @@ -242,6 +243,9 @@ public: LLFastTimer(NamedTimer::FrameState& timer) : mFrameState(&timer) { +#if TIME_FAST_TIMERS + U64 timer_start = get_cpu_clock_count_64(); +#endif #if FAST_TIMER_ON NamedTimer::FrameState* frame_state = &timer; U32 cur_time = get_cpu_clock_count_32(); @@ -256,10 +260,17 @@ public: mLastTimer = sCurTimer; sCurTimer = this; #endif +#if TIME_FAST_TIMERS + U64 timer_end = get_cpu_clock_count_64(); + sTimerCycles += timer_end - timer_start; +#endif } ~LLFastTimer() { +#if TIME_FAST_TIMERS + U64 timer_start = get_cpu_clock_count_64(); +#endif #if FAST_TIMER_ON NamedTimer::FrameState* frame_state = mFrameState; U32 cur_time = get_cpu_clock_count_32(); @@ -276,6 +287,11 @@ public: U32 total_time = cur_time - mStartTotalTime; last_timer->mStartSelfTime += total_time; #endif +#if TIME_FAST_TIMERS + U64 timer_end = get_cpu_clock_count_64(); + sTimerCycles += timer_end - timer_start; + sTimerCalls++; +#endif } @@ -297,11 +313,12 @@ public: static const NamedTimer* getTimerByName(const std::string& name); public: - static bool sPauseHistory; - static bool sResetHistory; + static bool sPauseHistory; + static bool sResetHistory; + static U64 sTimerCycles; + static U32 sTimerCalls; private: - typedef std::vector<LLFastTimer*> timer_stack_t; static LLFastTimer* sCurTimer; static S32 sCurFrameIndex; static S32 sLastFrameIndex; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 7ad5f9608f..37a28ac721 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -135,7 +135,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); - // determine which style flags need to be added programmatically by striping off the + // determine which style flags need to be added programmatically by stripping off the // style bits that are drawn by the underlying Freetype font U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle(); diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp index fa0abd55d0..c9090d388d 100644 --- a/indra/llui/llconsole.cpp +++ b/indra/llui/llconsole.cpp @@ -392,4 +392,10 @@ void LLConsole::addLine(const LLWString& wline, F32 size, const LLColor4 &color) Paragraph paragraph(wline, color, mTimer.getElapsedTimeF32(), mFont, (F32)getRect().getWidth() ); mParagraphs.push_back ( paragraph ); + + // remove old paragraphs which can't possibly be visible any more. ::draw() will do something similar but more conservative - we do this here because ::draw() isn't guaranteed to ever be called! (i.e. the console isn't visible) + while ((S32)mParagraphs.size() > llmax((S32)0, (S32)(mMaxLines))) + { + mParagraphs.pop_front(); + } } diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index 63faf44f9d..6a5b475134 100644 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -54,6 +54,7 @@ void LLDockableFloater::init(LLDockableFloater* thiz) LLDockableFloater::LLDockableFloater(LLDockControl* dockControl, const LLSD& key, const Params& params) : LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(true) + , mOverlapsScreenChannel(false) { init(this); } diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h index 2c339f4a3f..ae4f99e205 100644 --- a/indra/llui/lldockablefloater.h +++ b/indra/llui/lldockablefloater.h @@ -50,6 +50,16 @@ public: LOG_CLASS(LLDockableFloater); LLDockableFloater(LLDockControl* dockControl, const LLSD& key, const Params& params = getDefaultParams()); + + /** + * Constructor. + * @param dockControl a pointer to the doc control instance + * @param uniqueDocking - a flag defines is docking should work as tab(at one + * moment only one docked floater can be shown), also this flag defines is dock + * tongue should be used. + * @params key a floater key. + * @params params a floater parameters + */ LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking, const LLSD& key, const Params& params = getDefaultParams()); virtual ~LLDockableFloater(); @@ -85,6 +95,15 @@ public: LLDockControl* getDockControl(); + /** + * Returns true if screen channel should consider floater's size when drawing toasts. + * + * By default returns false. + */ + virtual bool overlapsScreenChannel() { return mOverlapsScreenChannel && getVisible() && isDocked(); } + virtual void setOverlapsScreenChannel(bool overlaps) { mOverlapsScreenChannel = overlaps; } + + bool getUniqueDocking() { return mUniqueDocking; } private: /** * Provides unique of dockable floater. @@ -105,6 +124,8 @@ private: * non exclusively. */ bool mUniqueDocking; + + bool mOverlapsScreenChannel; }; #endif /* LL_DOCKABLEFLOATER_H */ diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index 456a2925a3..1c3c8449c5 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -182,6 +182,14 @@ void LLDockControl::moveDockable() LLRect rootRect; mGetAllowedRectCallback(rootRect); + bool unique_docking = false; + LLDockableFloater* dockable_floater = + dynamic_cast<LLDockableFloater*> (mDockableFloater); + if (dockable_floater != NULL) + { + unique_docking = dockable_floater->getUniqueDocking(); + } + LLRect dockableRect = mDockableFloater->calcScreenRect(); S32 x = 0; S32 y = 0; @@ -208,7 +216,13 @@ void LLDockControl::moveDockable() case TOP: x = dockRect.getCenterX() - dockableRect.getWidth() / 2; - y = dockRect.mTop + mDockTongue->getHeight() + dockableRect.getHeight(); + y = dockRect.mTop + dockableRect.getHeight(); + // unique docking used with dock tongue, so add tongue height o the Y coordinate + if (unique_docking) + { + y += mDockTongue->getHeight(); + } + // check is dockable inside root view rect if (x < rootRect.mLeft) { @@ -273,7 +287,15 @@ void LLDockControl::forceRecalculatePosition() void LLDockControl::drawToungue() { - if (mEnabled) + bool unique_docking = false; + LLDockableFloater* dockable_floater = + dynamic_cast<LLDockableFloater*> (mDockableFloater); + if (dockable_floater != NULL) + { + unique_docking = dockable_floater->getUniqueDocking(); + } + + if (mEnabled && unique_docking) { mDockTongue->draw(mDockTongueX, mDockTongueY); } diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 09124c3013..3754d155cf 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -66,7 +66,7 @@ const LLRect& LLFlatListView::getItemsRect() const return mItemsPanel->getRect(); } -bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/) +bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/,bool rearrange /*= true*/) { if (!item) return false; if (value.isUndefined()) return false; @@ -97,8 +97,11 @@ bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null* // Children don't accept the focus item->setTabStop(false); - rearrangeItems(); - notifyParentItemsRectChanged(); + if (rearrange) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + } return true; } @@ -560,6 +563,8 @@ BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask) if ( ( key == KEY_UP || key == KEY_DOWN ) && mSelectedItemPairs.size() ) { + ensureSelectedVisible(); + /* LLRect visible_rc = getVisibleContentRect(); LLRect selected_rc = getLastSelectedItemRect(); @@ -572,7 +577,8 @@ BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask) // In case we are in accordion tab notify parent to show selected rectangle LLRect screen_rc; localRectToScreen(selected_rc, &screen_rc); - notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue())); + notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));*/ + handled = TRUE; } @@ -694,11 +700,30 @@ LLRect LLFlatListView::getSelectedItemsRect() void LLFlatListView::selectFirstItem () { selectItemPair(mItemPairs.front(), true); + ensureSelectedVisible(); } void LLFlatListView::selectLastItem () { selectItemPair(mItemPairs.back(), true); + ensureSelectedVisible(); +} + +void LLFlatListView::ensureSelectedVisible() +{ + LLRect visible_rc = getVisibleContentRect(); + LLRect selected_rc = getLastSelectedItemRect(); + + if ( !visible_rc.contains (selected_rc) ) + { + // But scroll in Items panel coordinates + scrollToShowRect(selected_rc); + } + + // In case we are in accordion tab notify parent to show selected rectangle + LLRect screen_rc; + localRectToScreen(selected_rc, &screen_rc); + notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue())); } @@ -958,7 +983,86 @@ S32 LLFlatListView::notify(const LLSD& info) return 1; } } + else if (info.has("rearrange")) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + return 1; + } return 0; } +void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items) +{ + LLSD action; + action.with("detach", LLSD()); + // Clear detached_items list + detached_items.clear(); + // Go through items and detach valid items, remove them from items panel + // and add to detached_items. + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + LLPanel* pItem = (*iter)->first; + if (1 == pItem->notify(action)) + { + selectItemPair((*iter), false); + mItemsPanel->removeChild(pItem); + detached_items.push_back(pItem); + } + } + if (!detached_items.empty()) + { + // Some items were detached, clean ourself from unusable memory + if (detached_items.size() == mItemPairs.size()) + { + // This way will be faster if all items were disconnected + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + (*iter)->first = NULL; + delete *iter; + } + mItemPairs.clear(); + // Also set items panel height to zero. + // Reshape it to allow reshaping of non-item children. + LLRect rc = mItemsPanel->getRect(); + rc.mBottom = rc.mTop; + mItemsPanel->reshape(rc.getWidth(), rc.getHeight()); + mItemsPanel->setRect(rc); + setNoItemsCommentVisible(true); + } + else + { + for (std::vector<LLPanel*>::const_iterator + detached_iter = detached_items.begin(), + detached_iter_end = detached_items.end(); + detached_iter != detached_iter_end; ++detached_iter) + { + LLPanel* pDetachedItem = *detached_iter; + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + item_pair_t* item_pair = *iter; + if (item_pair->first == pDetachedItem) + { + mItemPairs.erase(iter); + item_pair->first = NULL; + delete item_pair; + break; + } + } + } + rearrangeItems(); + } + notifyParentItemsRectChanged(); + } +} + //EOF diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index ba824ff2df..5999e79f61 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -124,6 +124,8 @@ public: /** Returns full rect of child panel */ const LLRect& getItemsRect() const; + LLRect getRequiredRect() { return getItemsRect(); } + /** Returns distance between items */ const S32 getItemsPad() { return mItemPad; } @@ -131,7 +133,7 @@ public: * Adds and item and LLSD value associated with it to the list at specified position * @return true if the item was added, false otherwise */ - virtual bool addItem(LLPanel * item, const LLSD& value = LLUUID::null, EAddPosition pos = ADD_BOTTOM); + virtual bool addItem(LLPanel * item, const LLSD& value = LLUUID::null, EAddPosition pos = ADD_BOTTOM, bool rearrange = true); /** * Insert item_to_add along with associated value to the list right after the after_item. @@ -269,6 +271,15 @@ public: virtual void clear(); /** + * Removes all items that can be detached from the list but doesn't destroy + * them, caller responsible to manage items after they are detached. + * Detachable item should accept "detach" action via notify() method, + * where it disconnect all callbacks, does other valuable routines and + * return 1. + */ + void detachItems(std::vector<LLPanel*>& detached_items); + + /** * Set comparator to use for future sorts. * * This class does NOT manage lifetime of the comparator @@ -359,6 +370,8 @@ protected: LLRect getSelectedItemsRect(); + void ensureSelectedVisible(); + private: void setItemsNoScrollWidth(S32 new_width) {mItemsNoScrollWidth = new_width - 2 * mBorderThickness;} diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index f7fd2dbdfe..845203b420 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2148,6 +2148,11 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) if (give_focus && !gFocusMgr.childHasKeyboardFocus(child)) { child->setFocus(TRUE); + // floater did not take focus, so relinquish focus to world + if (!child->hasFocus()) + { + gFocusMgr.setKeyboardFocus(NULL); + } } } @@ -2717,7 +2722,7 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o } params.from_xui = true; - setupParams(params, parent); + applyXUILayout(params, parent); initFromParams(params); initFloater(params); diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 5e15fa3919..1aaba88c49 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -247,7 +247,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o } p.from_xui = true; - setupParams(p, parent); + applyXUILayout(p, parent); LLLayoutStack* layout_stackp = LLUICtrlFactory::create<LLLayoutStack>(p); if (parent && layout_stackp) @@ -414,6 +414,16 @@ void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL au } } +void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_resize) +{ + LayoutPanel* panel = findEmbeddedPanelByName(panel_name); + + if (panel) + { + panel->mUserResize = user_resize; + } +} + bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_widthp, S32* min_heightp) { LayoutPanel* panel = findEmbeddedPanelByName(panel_name); diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index c1af428674..cde383b047 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -80,6 +80,7 @@ public: S32 getNumPanels() { return mPanels.size(); } void updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize); + void setPanelUserResize(const std::string& panel_name, BOOL user_resize); /** * Gets minimal width and/or height of the specified by name panel. diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 202ed04fbc..2648cbf08d 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -23,7 +23,7 @@ * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. @@ -1208,22 +1208,41 @@ void LLMenuItemBranchGL::openMenu() branch->arrange(); - LLRect rect = branch->getRect(); + LLRect branch_rect = branch->getRect(); // calculate root-view relative position for branch menu S32 left = getRect().mRight; S32 top = getRect().mTop - getRect().mBottom; localPointToOtherView(left, top, &left, &top, branch->getParent()); - rect.setLeftTopAndSize( left, top, - rect.getWidth(), rect.getHeight() ); + branch_rect.setLeftTopAndSize( left, top, + branch_rect.getWidth(), branch_rect.getHeight() ); if (branch->getCanTearOff()) { - rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS); + branch_rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS); + } + branch->setRect( branch_rect ); + + // if branch extends outside of menu region change the direction it opens in + S32 x, y; + S32 delta_x = 0; + S32 delta_y = 0; + branch->localPointToOtherView( 0, 0, &x, &y, branch->getParent() ); + if( y < menu_region_rect.mBottom ) + { + // open upwards if menu extends past bottom + // adjust by the height of the menu item branch since it is a submenu + delta_y = branch_rect.getHeight() - getRect().getHeight(); } - branch->setRect( rect ); - branch->translateIntoRectWithExclusion( menu_region_rect, getMenu()->getRect(), FALSE ); + + if( x + branch_rect.getWidth() > menu_region_rect.mRight ) + { + // move sub-menu over to left side + delta_x = llmax(-x, ( -(branch_rect.getWidth() + getRect().getWidth()))); + } + branch->translate( delta_x, delta_y ); + branch->setVisible( TRUE ); branch->getParent()->sendChildToFront(branch); @@ -3610,6 +3629,11 @@ public: LLContextMenuBranch(const Params&); + virtual ~LLContextMenuBranch() + { + delete mBranch; + } + // called to rebuild the draw label virtual void buildDrawLabel( void ); diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index 1891bca36c..aea7c5f87c 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -50,6 +50,12 @@ const F32 FLOAT_THRESHOLD = 0.00001f; S32 LLMultiSlider::mNameCounter = 0; +LLMultiSlider::SliderParams::SliderParams() +: name("name"), + value("value", 0.f) +{ +} + LLMultiSlider::Params::Params() : max_sliders("max_sliders", 1), allow_overlap("allow_overlap", false), @@ -63,7 +69,8 @@ LLMultiSlider::Params::Params() triangle_color("triangle_color"), mouse_down_callback("mouse_down_callback"), mouse_up_callback("mouse_up_callback"), - thumb_width("thumb_width") + thumb_width("thumb_width"), + sliders("slider") { name = "multi_slider_bar"; mouse_opaque(true); @@ -99,6 +106,20 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p) { setMouseUpCallback(initCommitCallback(p.mouse_up_callback)); } + + for (LLInitParam::ParamIterator<SliderParams>::const_iterator it = p.sliders().begin(); + it != p.sliders().end(); + ++it) + { + if (it->name.isProvided()) + { + addSlider(it->value, it->name); + } + else + { + addSlider(it->value); + } + } } LLMultiSlider::~LLMultiSlider() @@ -230,6 +251,30 @@ const std::string& LLMultiSlider::addSlider(F32 val) return mCurSlider; } +void LLMultiSlider::addSlider(F32 val, const std::string& name) +{ + F32 initVal = val; + + if(mValue.size() >= mMaxNumSliders) { + return; + } + + bool foundOne = findUnusedValue(initVal); + if(!foundOne) { + return; + } + + // add a new thumb rect + mThumbRects[name] = LLRect( 0, getRect().getHeight(), mThumbWidth, 0 ); + + // add the value and set the current slider to this one + mValue.insert(name, initVal); + mCurSlider = name; + + // move the slider + setSliderValue(mCurSlider, initVal, TRUE); +} + bool LLMultiSlider::findUnusedValue(F32& initVal) { bool firstTry = true; @@ -572,7 +617,6 @@ void LLMultiSlider::draw() LLF32UICtrl::draw(); } - boost::signals2::connection LLMultiSlider::setMouseDownCallback( const commit_signal_t::slot_type& cb ) { if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t(); diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h index f8e43a0470..88576da85b 100644 --- a/indra/llui/llmultislider.h +++ b/indra/llui/llmultislider.h @@ -41,6 +41,13 @@ class LLUICtrlFactory; class LLMultiSlider : public LLF32UICtrl { public: + struct SliderParams : public LLInitParam::Block<SliderParams> + { + Optional<std::string> name; + Mandatory<F32> value; + SliderParams(); + }; + struct Params : public LLInitParam::Block<Params, LLF32UICtrl::Params> { Optional<S32> max_sliders; @@ -60,6 +67,7 @@ public: mouse_up_callback; Optional<S32> thumb_width; + Multiple<SliderParams> sliders; Params(); }; @@ -68,13 +76,13 @@ protected: friend class LLUICtrlFactory; public: virtual ~LLMultiSlider(); - void setSliderValue(const std::string& name, F32 value, BOOL from_event = FALSE); - F32 getSliderValue(const std::string& name) const; + void setSliderValue(const std::string& name, F32 value, BOOL from_event = FALSE); + F32 getSliderValue(const std::string& name) const; - const std::string& getCurSlider() const { return mCurSlider; } - F32 getCurSliderValue() const { return getSliderValue(mCurSlider); } - void setCurSlider(const std::string& name); - void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mCurSlider, val, from_event); } + const std::string& getCurSlider() const { return mCurSlider; } + F32 getCurSliderValue() const { return getSliderValue(mCurSlider); } + void setCurSlider(const std::string& name); + void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mCurSlider, val, from_event); } /*virtual*/ void setValue(const LLSD& value); /*virtual*/ LLSD getValue() const { return mValue; } @@ -82,12 +90,13 @@ public: boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb ); boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); - bool findUnusedValue(F32& initVal); + bool findUnusedValue(F32& initVal); const std::string& addSlider(); const std::string& addSlider(F32 val); - void deleteSlider(const std::string& name); - void deleteCurSlider() { deleteSlider(mCurSlider); } - void clear(); + void addSlider(F32 val, const std::string& name); + void deleteSlider(const std::string& name); + void deleteCurSlider() { deleteSlider(mCurSlider); } + void clear(); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); @@ -109,7 +118,8 @@ protected: LLRect mDragStartThumbRect; S32 mThumbWidth; - std::map<std::string, LLRect> mThumbRects; + std::map<std::string, LLRect> + mThumbRects; LLUIColor mTrackColor; LLUIColor mThumbOutlineColor; LLUIColor mThumbCenterColor; diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp index 7323323d8c..f4434a0f78 100644 --- a/indra/llui/llmultisliderctrl.cpp +++ b/indra/llui/llmultisliderctrl.cpp @@ -65,7 +65,8 @@ LLMultiSliderCtrl::Params::Params() text_color("text_color"), text_disabled_color("text_disabled_color"), mouse_down_callback("mouse_down_callback"), - mouse_up_callback("mouse_up_callback") + mouse_up_callback("mouse_up_callback"), + sliders("slider") { mouse_opaque = true; } @@ -161,6 +162,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p) S32 slider_left = label_width ? label_width + multi_sliderctrl_spacing : 0; LLRect slider_rect( slider_left, top, slider_right, bottom ); LLMultiSlider::Params params; + params.sliders = p.sliders; params.rect(slider_rect); params.commit_callback.function( LLMultiSliderCtrl::onSliderCommit ); params.mouse_down_callback( p.mouse_down_callback ); diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h index 16d07541f2..e8366d09c2 100644 --- a/indra/llui/llmultisliderctrl.h +++ b/indra/llui/llmultisliderctrl.h @@ -69,6 +69,8 @@ public: Optional<CommitCallbackParam> mouse_down_callback, mouse_up_callback; + Multiple<LLMultiSlider::SliderParams> sliders; + Params(); }; diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index fe4fbe7510..ee6ec0f88f 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -10,10 +10,10 @@ */ #include "linden_common.h" - #include "llnotificationslistener.h" - #include "llnotifications.h" +#include "llsd.h" +#include "llui.h" LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) : LLEventAPI("LLNotifications", @@ -24,6 +24,47 @@ LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications "Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n" "If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.", &LLNotificationsListener::requestAdd); + add("listChannels", + "Post to [\"reply\"] a map of info on existing channels", + &LLNotificationsListener::listChannels, + LLSD().with("reply", LLSD())); + add("listChannelNotifications", + "Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]", + &LLNotificationsListener::listChannelNotifications, + LLSD().with("reply", LLSD()).with("channel", LLSD())); + add("respond", + "Respond to notification [\"uuid\"] with data in [\"response\"]", + &LLNotificationsListener::respond, + LLSD().with("uuid", LLSD())); + add("cancel", + "Cancel notification [\"uuid\"]", + &LLNotificationsListener::cancel, + LLSD().with("uuid", LLSD())); + add("ignore", + "Ignore future notification [\"name\"]\n" + "(from <notification name= > in notifications.xml)\n" + "according to boolean [\"ignore\"].\n" + "If [\"name\"] is omitted or undefined, [un]ignore all future notifications.\n" + "Note that ignored notifications are not forwarded unless intercepted before\n" + "the \"Ignore\" channel.", + &LLNotificationsListener::ignore); + add("forward", + "Forward to [\"pump\"] future notifications on channel [\"channel\"]\n" + "according to boolean [\"forward\"]. When enabled, only types matching\n" + "[\"types\"] are forwarded, as follows:\n" + "omitted or undefined: forward all notifications\n" + "string: forward only the specific named [sig]type\n" + "array of string: forward any notification matching any named [sig]type.\n" + "When boolean [\"respond\"] is true, we auto-respond to each forwarded\n" + "notification.", + &LLNotificationsListener::forward, + LLSD().with("channel", LLSD())); +} + +// This is here in the .cpp file so we don't need the definition of class +// Forwarder in the header file. +LLNotificationsListener::~LLNotificationsListener() +{ } void LLNotificationsListener::requestAdd(const LLSD& event_data) const @@ -57,3 +98,235 @@ void LLNotificationsListener::NotificationResponder(const std::string& reply_pum reponse_event["response"] = response; LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event); } + +void LLNotificationsListener::listChannels(const LLSD& params) const +{ + LLReqID reqID(params); + LLSD response(reqID.makeResponse()); + for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()), + cmend(mNotifications.mChannels.end()); + cmi != cmend; ++cmi) + { + LLSD channelInfo; + channelInfo["parent"] = cmi->second->getParentChannelName(); + response[cmi->first] = channelInfo; + } + LLEventPumps::instance().obtain(params["reply"]).post(response); +} + +void LLNotificationsListener::listChannelNotifications(const LLSD& params) const +{ + LLReqID reqID(params); + LLSD response(reqID.makeResponse()); + LLNotificationChannelPtr channel(mNotifications.getChannel(params["channel"])); + if (channel) + { + LLSD notifications(LLSD::emptyArray()); + for (LLNotificationChannel::Iterator ni(channel->begin()), nend(channel->end()); + ni != nend; ++ni) + { + notifications.append(asLLSD(*ni)); + } + response["notifications"] = notifications; + } + LLEventPumps::instance().obtain(params["reply"]).post(response); +} + +void LLNotificationsListener::respond(const LLSD& params) const +{ + LLNotificationPtr notification(mNotifications.find(params["uuid"])); + if (notification) + { + notification->respond(params["response"]); + } +} + +void LLNotificationsListener::cancel(const LLSD& params) const +{ + LLNotificationPtr notification(mNotifications.find(params["uuid"])); + if (notification) + { + mNotifications.cancel(notification); + } +} + +void LLNotificationsListener::ignore(const LLSD& params) const +{ + // Calling a method named "ignore", but omitting its "ignore" Boolean + // argument, should by default cause something to be ignored. Explicitly + // pass ["ignore"] = false to cancel ignore. + bool ignore = true; + if (params.has("ignore")) + { + ignore = params["ignore"].asBoolean(); + } + // This method can be used to affect either a single notification name or + // all future notifications. The two use substantially different mechanisms. + if (params["name"].isDefined()) + { + // ["name"] was passed: ignore just that notification + LLUI::sSettingGroups["ignores"]->setBOOL(params["name"], ignore); + } + else + { + // no ["name"]: ignore all future notifications + mNotifications.setIgnoreAllNotifications(ignore); + } +} + +class LLNotificationsListener::Forwarder: public LLEventTrackable +{ + LOG_CLASS(LLNotificationsListener::Forwarder); +public: + Forwarder(LLNotifications& llnotifications, const std::string& channel): + mNotifications(llnotifications), + mRespond(false) + { + // Connect to the specified channel on construction. Because + // LLEventTrackable is a base, we should automatically disconnect when + // destroyed. + LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel)); + if (channelptr) + { + // Insert our processing as a "passed filter" listener. This way + // we get to run before all the "changed" listeners, and we get to + // swipe it (hide it from the other listeners) if desired. + channelptr->connectPassedFilter(boost::bind(&Forwarder::handle, this, _1)); + } + } + + void setPumpName(const std::string& name) { mPumpName = name; } + void setTypes(const LLSD& types) { mTypes = types; } + void setRespond(bool respond) { mRespond = respond; } + +private: + bool handle(const LLSD& notification) const; + bool matchType(const LLSD& filter, const std::string& type) const; + + LLNotifications& mNotifications; + std::string mPumpName; + LLSD mTypes; + bool mRespond; +}; + +void LLNotificationsListener::forward(const LLSD& params) +{ + std::string channel(params["channel"]); + // First decide whether we're supposed to start forwarding or stop it. + // Default to true. + bool forward = true; + if (params.has("forward")) + { + forward = params["forward"].asBoolean(); + } + if (! forward) + { + // This is a request to stop forwarding notifications on the specified + // channel. The rest of the params don't matter. + // Because mForwarders contains scoped_ptrs, erasing the map entry + // DOES delete the heap Forwarder object. Because Forwarder derives + // from LLEventTrackable, destroying it disconnects it from the + // channel. + mForwarders.erase(channel); + return; + } + // From here on, we know we're being asked to start (or modify) forwarding + // on the specified channel. Find or create an appropriate Forwarder. + ForwarderMap::iterator + entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first); + if (! entry->second) + { + entry->second.reset(new Forwarder(mNotifications, channel)); + } + // Now, whether this Forwarder is brand-new or not, update it with the new + // request info. + Forwarder& fwd(*entry->second); + fwd.setPumpName(params["pump"]); + fwd.setTypes(params["types"]); + fwd.setRespond(params["respond"]); +} + +bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const +{ + LL_INFOS("LLNotificationsListener") << "handle(" << notification << ")" << LL_ENDL; + if (notification["sigtype"].asString() == "delete") + { + LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL; + // let other listeners see the "delete" operation + return false; + } + LLNotificationPtr note(mNotifications.find(notification["id"])); + if (! note) + { + LL_INFOS("LLNotificationsListener") << notification["id"] << " not found" << LL_ENDL; + return false; + } + if (! matchType(mTypes, note->getType())) + { + LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL; + // We're not supposed to intercept this particular notification. Let + // other listeners process it. + return false; + } + LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL; + // This is a notification we care about. Forward it through specified + // LLEventPump. + LLEventPumps::instance().obtain(mPumpName).post(asLLSD(note)); + // Are we also being asked to auto-respond? + if (mRespond) + { + LL_INFOS("LLNotificationsListener") << "should respond" << LL_ENDL; + note->respond(LLSD::emptyMap()); + // Did that succeed in removing the notification? Only cancel() if + // it's still around -- otherwise we get an LL_ERRS crash! + note = mNotifications.find(notification["id"]); + if (note) + { + LL_INFOS("LLNotificationsListener") << "respond() didn't clear, canceling" << LL_ENDL; + mNotifications.cancel(note); + } + } + // If we've auto-responded to this notification, then it's going to be + // deleted. Other listeners would get the change operation, try to look it + // up and be baffled by lookup failure. So when we auto-respond, suppress + // this notification: don't pass it to other listeners. + return mRespond; +} + +bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const +{ + // Decide whether this notification matches filter: + // undefined: forward all notifications + if (filter.isUndefined()) + { + return true; + } + // array of string: forward any notification matching any named type + if (filter.isArray()) + { + for (LLSD::array_const_iterator ti(filter.beginArray()), tend(filter.endArray()); + ti != tend; ++ti) + { + if (ti->asString() == type) + { + return true; + } + } + // Didn't match any entry in the array + return false; + } + // string: forward only the specific named type + return (filter.asString() == type); +} + +LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note) +{ + LLSD notificationInfo(note->asLLSD()); + // For some reason the following aren't included in LLNotification::asLLSD(). + notificationInfo["summary"] = note->summarize(); + notificationInfo["id"] = note->id(); + notificationInfo["type"] = note->getType(); + notificationInfo["message"] = note->getMessage(); + notificationInfo["label"] = note->getLabel(); + return notificationInfo; +} diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h index 9b405d7b4b..de208b57f0 100644 --- a/indra/llui/llnotificationslistener.h +++ b/indra/llui/llnotificationslistener.h @@ -13,6 +13,10 @@ #define LL_LLNOTIFICATIONSLISTENER_H #include "lleventapi.h" +#include "llnotificationptr.h" +#include <boost/shared_ptr.hpp> +#include <map> +#include <string> class LLNotifications; class LLSD; @@ -21,13 +25,27 @@ class LLNotificationsListener : public LLEventAPI { public: LLNotificationsListener(LLNotifications & notifications); + ~LLNotificationsListener(); +private: void requestAdd(LLSD const & event_data) const; -private: void NotificationResponder(const std::string& replypump, const LLSD& notification, const LLSD& response) const; + + void listChannels(const LLSD& params) const; + void listChannelNotifications(const LLSD& params) const; + void respond(const LLSD& params) const; + void cancel(const LLSD& params) const; + void ignore(const LLSD& params) const; + void forward(const LLSD& params); + + static LLSD asLLSD(LLNotificationPtr); + + class Forwarder; + typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap; + ForwarderMap mForwarders; LLNotifications & mNotifications; }; diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 738a96f730..db32882438 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -452,7 +452,7 @@ void LLPanel::initFromParams(const LLPanel::Params& p) parseFollowsFlags(p); setToolTip(p.tool_tip()); - setSaveToXML(p.from_xui); + setFromXUI(p.from_xui); mHoverCursor = getCursorFromString(p.hover_cursor); @@ -542,7 +542,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu } params.from_xui = true; - setupParams(params, parent); + applyXUILayout(params, parent); { LLFastTimer timer(FTM_PANEL_CONSTRUCTION); initFromParams(params); diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp index 997b9c13f8..4087b484aa 100644 --- a/indra/llui/llradiogroup.cpp +++ b/indra/llui/llradiogroup.cpp @@ -116,6 +116,10 @@ void LLRadioGroup::initFromParams(const Params& p) item_params.font.setIfNotProvided(mFont); // apply radio group font by default item_params.commit_callback.function = boost::bind(&LLRadioGroup::onClickButton, this, _1); item_params.from_xui = p.from_xui; + if (p.from_xui) + { + applyXUILayout(item_params, this); + } LLRadioCtrl* item = LLUICtrlFactory::create<LLRadioCtrl>(item_params, this); mRadioButtons.push_back(item); diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 544352176a..7238d903a3 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -353,7 +353,7 @@ LLScrollListCheck::LLScrollListCheck(const LLScrollListCell::Params& p) { LLCheckBoxCtrl::Params checkbox_p; checkbox_p.name("checkbox"); - checkbox_p.rect.left(0).bottom(0).width(p.width).height(p.width); + checkbox_p.rect = LLRect(0, p.width, p.width, 0); checkbox_p.enabled(p.enabled); checkbox_p.initial_value(p.value()); diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index d6d46654d5..20a1ab7af3 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -75,10 +75,8 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) static LLUICachedControl<S32> spinctrl_spacing ("UISpinctrlSpacing", 0); static LLUICachedControl<S32> spinctrl_btn_width ("UISpinctrlBtnWidth", 0); static LLUICachedControl<S32> spinctrl_btn_height ("UISpinctrlBtnHeight", 0); - S32 top = getRect().getHeight(); - S32 bottom = top - 2 * spinctrl_btn_height; - S32 centered_top = top; - S32 centered_bottom = bottom; + S32 centered_top = getRect().getHeight(); + S32 centered_bottom = getRect().getHeight() - 2 * spinctrl_btn_height; S32 btn_left = 0; // reserve space for spinner S32 label_width = llclamp(p.label_width(), 0, llmax(0, getRect().getWidth() - 40)); @@ -105,25 +103,15 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) // Spin buttons LLButton::Params up_button_params(p.up_button); - up_button_params.rect - .left(btn_left) - .top(top) - .right(btn_right) - .height(spinctrl_btn_height); + up_button_params.rect = LLRect(btn_left, getRect().getHeight(), btn_right, getRect().getHeight() - spinctrl_btn_height); up_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2)); up_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2)); mUpBtn = LLUICtrlFactory::create<LLButton>(up_button_params); addChild(mUpBtn); - LLRect down_rect( btn_left, top - spinctrl_btn_height, btn_right, bottom ); - LLButton::Params down_button_params(p.down_button); - down_button_params.rect - .left(btn_left) - .right(btn_right) - .bottom(bottom) - .height(spinctrl_btn_height); + down_button_params.rect = LLRect(btn_left, getRect().getHeight() - spinctrl_btn_height, btn_right, getRect().getHeight() - 2 * spinctrl_btn_height); down_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2)); down_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2)); mDownBtn = LLUICtrlFactory::create<LLButton>(down_button_params); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 83e2e3db50..327dd01612 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -266,8 +266,6 @@ bool LLTabContainer::addChild(LLView* view, S32 tab_group) if (panelp) { - panelp->setSaveToXML(TRUE); - addTabPanel(TabPanelParams().panel(panelp).label(panelp->getLabel()).is_placeholder(dynamic_cast<LLPlaceHolderPanel*>(view) != NULL)); return true; } @@ -1019,12 +1017,10 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) { if (textbox) { - textbox->setSaveToXML(false); addChild( textbox, 0 ); } if (btn) { - btn->setSaveToXML(false); addChild( btn, 0 ); } } @@ -1747,24 +1743,20 @@ void LLTabContainer::initButtons() } } - mPrevArrowBtn->setSaveToXML(false); mPrevArrowBtn->setTabStop(FALSE); addChild(mPrevArrowBtn); - mNextArrowBtn->setSaveToXML(false); mNextArrowBtn->setTabStop(FALSE); addChild(mNextArrowBtn); if (mJumpPrevArrowBtn) { - mJumpPrevArrowBtn->setSaveToXML(false); mJumpPrevArrowBtn->setTabStop(FALSE); addChild(mJumpPrevArrowBtn); } if (mJumpNextArrowBtn) { - mJumpNextArrowBtn->setSaveToXML(false); mJumpNextArrowBtn->setTabStop(FALSE); addChild(mJumpNextArrowBtn); } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index cb0907a771..7447a984ac 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -842,7 +842,7 @@ BOOL LLTextBase::handleMouseUp(S32 x, S32 y, MASK mask) { // Did we just click on a link? if (cur_segment->getStyle() - && cur_segment->getStyle()->isLink()) + && cur_segment->getStyle()->isLink()) { // *TODO: send URL here? mURLClickSignal(this, LLSD() ); @@ -962,7 +962,10 @@ void LLTextBase::draw() reflow(); // then update scroll position, as cursor may have moved - updateScrollFromCursor(); + if (!mReadOnly) + { + updateScrollFromCursor(); + } LLRect doc_rect; if (mScroller) @@ -1474,7 +1477,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) } } -void LLTextBase::setText(const LLStringExplicit &utf8str ,const LLStyle::Params& input_params) +void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params) { // clear out the existing text and segments getViewModel()->setDisplay(LLWStringUtil::null); @@ -1932,11 +1935,19 @@ void LLTextBase::endOfLine() void LLTextBase::startOfDoc() { setCursorPos(0); + if (mScroller) + { + mScroller->goToTop(); + } } void LLTextBase::endOfDoc() { setCursorPos(getLength()); + if (mScroller) + { + mScroller->goToBottom(); + } } void LLTextBase::changePage( S32 delta ) @@ -2001,6 +2012,16 @@ void LLTextBase::changeLine( S32 delta ) setCursorPos(new_cursor_pos, true); } +bool LLTextBase::scrolledToStart() +{ + return mScroller->isAtTop(); +} + +bool LLTextBase::scrolledToEnd() +{ + return mScroller->isAtBottom(); +} + bool LLTextBase::setCursor(S32 row, S32 column) { @@ -2299,14 +2320,14 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele S32 end = llmin( selection_start, seg_end ); S32 length = end - start; font->render(text, start, - rect.mLeft, rect.mTop, - color, - LLFontGL::LEFT, LLFontGL::TOP, - 0, - mStyle->getShadowType(), - length, rect.getWidth(), - &right_x, - mEditor.getUseEllipses()); + rect.mLeft, rect.mTop, + color, + LLFontGL::LEFT, LLFontGL::TOP, + LLFontGL::NORMAL, + mStyle->getShadowType(), + length, rect.getWidth(), + &right_x, + mEditor.getUseEllipses()); } rect.mLeft = (S32)ceil(right_x); @@ -2318,14 +2339,14 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele S32 length = end - start; font->render(text, start, - rect.mLeft, rect.mTop, - LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ), - LLFontGL::LEFT, LLFontGL::TOP, - 0, - LLFontGL::NO_SHADOW, - length, rect.getWidth(), - &right_x, - mEditor.getUseEllipses()); + rect.mLeft, rect.mTop, + LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ), + LLFontGL::LEFT, LLFontGL::TOP, + LLFontGL::NORMAL, + LLFontGL::NO_SHADOW, + length, rect.getWidth(), + &right_x, + mEditor.getUseEllipses()); } rect.mLeft = (S32)ceil(right_x); if( selection_end < seg_end ) @@ -2335,14 +2356,14 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele S32 end = seg_end; S32 length = end - start; font->render(text, start, - rect.mLeft, rect.mTop, - color, - LLFontGL::LEFT, LLFontGL::TOP, - 0, - mStyle->getShadowType(), - length, rect.getWidth(), - &right_x, - mEditor.getUseEllipses()); + rect.mLeft, rect.mTop, + color, + LLFontGL::LEFT, LLFontGL::TOP, + LLFontGL::NORMAL, + mStyle->getShadowType(), + length, rect.getWidth(), + &right_x, + mEditor.getUseEllipses()); } return right_x; } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index a1f8ba39ae..038b9eaa62 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -180,8 +180,11 @@ public: void changePage( S32 delta ); void changeLine( S32 delta ); + bool scrolledToStart(); + bool scrolledToEnd(); const LLFontGL* getDefaultFont() const { return mDefaultFont; } + LLStyle::Params getDefaultStyle(); public: // Fired when a URL link is clicked @@ -254,7 +257,6 @@ protected: LLTextBase(const Params &p); virtual ~LLTextBase(); void initFromParams(const Params& p); - LLStyle::Params getDefaultStyle(); virtual void onValueChange(S32 start, S32 end); // draw methods diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 1ea6b66a93..d0ed3b6fca 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1915,6 +1915,7 @@ namespace LLInitParam green = color.mV[VGREEN]; blue = color.mV[VBLUE]; alpha = color.mV[VALPHA]; + control.set("", false); } void TypeValues<LLUIColor>::declareValues() @@ -2046,12 +2047,16 @@ namespace LLInitParam void TypedParam<LLRect>::setBlockFromValue() { - left = mData.mValue.mLeft; - right = mData.mValue.mRight; - bottom = mData.mValue.mBottom; - top = mData.mValue.mTop; - width.setProvided(false); - height.setProvided(false); + // because of the ambiguity in specifying a rect by position and/or dimensions + // we clear the "provided" flag so that values from xui/etc have priority + // over those calculated from the rect object + + left.set(mData.mValue.mLeft, false); + right.set(mData.mValue.mRight, false); + bottom.set(mData.mValue.mBottom, false); + top.set(mData.mValue.mTop, false); + width.set(mData.mValue.getWidth(), false); + height.set(mData.mValue.getHeight(), false); } TypedParam<LLCoordGL>::TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 6788f29ba9..b1fa6add67 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -184,8 +184,6 @@ public: { T* widget = NULL; - T::setupParams(params, parent); - if (!params.validateBlock()) { llwarns << getInstance()->getCurFileName() << ": Invalid parameter block for " << typeid(T).name() << llendl; @@ -310,6 +308,7 @@ fail: // Apply layout transformations, usually munging rect params.from_xui = true; + T::applyXUILayout(params, parent); T* widget = createWidget<T>(params, parent); typedef typename T::child_registry_t registry_t; diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp index 1dfc281d93..966d919dc7 100644 --- a/indra/llui/lluiimage.cpp +++ b/indra/llui/lluiimage.cpp @@ -168,6 +168,7 @@ namespace LLInitParam if (name() == "none") { mData.mValue = NULL; + return; } LLUIImage* imagep = LLUI::getUIImage(name()); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 7350457274..f7528bc62a 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -80,7 +80,7 @@ std::string LLUrlEntryBase::escapeUrl(const std::string &url) const "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789" - "-._~!$?&()*+,@:;=/%"; + "-._~!$?&()*+,@:;=/%#"; std::sort(no_escape_chars.begin(), no_escape_chars.end()); initialized = true; @@ -201,8 +201,12 @@ std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string) // 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); + mPattern = boost::regex("(" + "\\bwww\\.\\S+\\.\\S+" // i.e. www.FOO.BAR + "|" // or + "\\b[^ \\t\\n\\r\\f\\v:/]+\\.(?:com|net|edu|org)[^[:space:][:alnum:]]*\\>" // i.e. FOO.net + ")", + boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_http.xml"; mTooltip = LLTrans::getString("TooltipHttpUrl"); } diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index afcff0d409..ad5c0911f8 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -223,3 +223,23 @@ bool LLUrlRegistry::hasUrl(const LLWString &text) LLUrlMatch match; return findUrl(text, match); } + +bool LLUrlRegistry::isUrl(const std::string &text) +{ + LLUrlMatch match; + if (findUrl(text, match)) + { + return (match.getStart() == 0 && match.getEnd() >= text.size()-1); + } + return false; +} + +bool LLUrlRegistry::isUrl(const LLWString &text) +{ + LLUrlMatch match; + if (findUrl(text, match)) + { + return (match.getStart() == 0 && match.getEnd() >= text.size()-1); + } + return false; +} diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index d7800d8cfc..399ee0a988 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -85,6 +85,10 @@ public: bool hasUrl(const std::string &text); bool hasUrl(const LLWString &text); + // return true if the given string is a URL that findUrl would match + bool isUrl(const std::string &text); + bool isUrl(const LLWString &text); + private: LLUrlRegistry(); friend class LLSingleton<LLUrlRegistry>; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index a8d8626e49..f1b08c380b 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -126,7 +126,7 @@ LLView::LLView(const LLView::Params& p) : mName(p.name), mParentView(NULL), mReshapeFlags(FOLLOWS_NONE), - mSaveToXML(p.from_xui), + mFromXUI(p.from_xui), mIsFocusRoot(FALSE), mLastVisible(FALSE), mNextInsertionOrdinal(0), @@ -2479,7 +2479,7 @@ static bool get_last_child_rect(LLView* parent, LLRect *rect) for (;itor != parent->getChildList()->end(); ++itor) { LLView *last_view = (*itor); - if (last_view->getSaveToXML()) + if (last_view->getFromXUI()) { *rect = last_view->getRect(); return true; @@ -2489,7 +2489,7 @@ static bool get_last_child_rect(LLView* parent, LLRect *rect) } //static -void LLView::setupParams(LLView::Params& p, LLView* parent) +void LLView::applyXUILayout(LLView::Params& p, LLView* parent) { const S32 VPAD = 4; const S32 MIN_WIDGET_HEIGHT = 10; @@ -2509,7 +2509,7 @@ void LLView::setupParams(LLView::Params& p, LLView* parent) LLRect last_rect = parent->getLocalRect(); bool layout_topleft = (p.layout() == "topleft"); - if (layout_topleft && p.from_xui) + if (layout_topleft) { //invert top to bottom if (p.rect.top.isProvided()) p.rect.top = parent_rect.getHeight() - p.rect.top; @@ -2535,10 +2535,10 @@ void LLView::setupParams(LLView::Params& p, LLView* parent) p.rect.right.setProvided(false); // recalculate the right } } - else if (p.from_xui) // only do negative coordinate magic for XUI + else { - if (p.rect.left < 0) p.rect.left = p.rect.left + parent_rect.getWidth(); - if (p.rect.right < 0) p.rect.right = p.rect.right + parent_rect.getWidth(); + if (p.rect.left.isProvided() && p.rect.left < 0) p.rect.left = p.rect.left + parent_rect.getWidth(); + if (p.rect.right.isProvided() && p.rect.right < 0) p.rect.right = p.rect.right + parent_rect.getWidth(); } if (p.center_vert) { @@ -2556,15 +2556,15 @@ void LLView::setupParams(LLView::Params& p, LLView* parent) p.rect.top.setProvided(false); // recalculate the top } } - else if (p.from_xui) + else { - if (p.rect.bottom < 0) p.rect.bottom = p.rect.bottom + parent_rect.getHeight(); - if (p.rect.top < 0) p.rect.top = p.rect.top + parent_rect.getHeight(); + if (p.rect.bottom.isProvided() && p.rect.bottom < 0) p.rect.bottom = p.rect.bottom + parent_rect.getHeight(); + if (p.rect.top.isProvided() && p.rect.top < 0) p.rect.top = p.rect.top + parent_rect.getHeight(); } // DEPRECATE: automatically fall back to height of MIN_WIDGET_HEIGHT pixels - if (!p.rect.height.isProvided() && !p.rect.top.isProvided()) + if (!p.rect.height.isProvided() && !p.rect.top.isProvided() && p.rect.height == 0) { p.rect.height = MIN_WIDGET_HEIGHT; } @@ -2663,7 +2663,7 @@ static void convert_to_relative_layout(LLView::Params& p, LLView* parent) // Use setupParams to get the final widget rectangle // according to our wacky layout rules. LLView::Params final = p; - LLView::setupParams(final, parent); + LLView::applyXUILayout(final, parent); // Must actually extract the rectangle to get consistent // right = left+width, top = bottom+height LLRect final_rect = final.rect; diff --git a/indra/llui/llview.h b/indra/llui/llview.h index f8460f5361..c4d7313743 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -395,8 +395,8 @@ public: void parseFollowsFlags(const LLView::Params& params); // Some widgets, like close box buttons, don't need to be saved - BOOL getSaveToXML() const { return mSaveToXML; } - void setSaveToXML(BOOL b) { mSaveToXML = b; } + BOOL getFromXUI() const { return mFromXUI; } + void setFromXUI(BOOL b) { mFromXUI = b; } typedef enum e_hit_test_type { @@ -498,7 +498,7 @@ public: // Set up params after XML load before calling new(), // usually to adjust layout. - static void setupParams(Params& p, LLView* parent); + static void applyXUILayout(Params& p, LLView* parent); // For re-export of floaters and panels, convert the coordinate system // to be top-left based. @@ -573,7 +573,7 @@ private: LLUIString mToolTipMsg; // isNull() is true if none. U8 mSoundFlags; - BOOL mSaveToXML; + BOOL mFromXUI; BOOL mIsFocusRoot; BOOL mUseBoundingRect; // hit test against bounding rectangle that includes all child elements diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h index 2244ccc146..799808aa8b 100644 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h +++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h @@ -37,10 +37,16 @@ #include <cstdio> +extern "C" { +#include <sys/types.h> +#include <unistd.h> +} + ///////////////////////////////////////////////////////////////////////// // Debug/Info/Warning macros. #define MSGMODULEFOO "(media plugin)" #define STDERRMSG(...) do{\ + fprintf(stderr, " pid:%d: ", (int)getpid());\ fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\ fprintf(stderr, __VA_ARGS__);\ fputc('\n',stderr);\ diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp index 5bb0ef5a99..484948bd9f 100644 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp +++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp @@ -108,11 +108,10 @@ gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf) slvideo = GST_SLVIDEO(bsink); -#if 0 - fprintf(stderr, "\n\ntransferring a frame of %dx%d <- %p (%d)\n\n", - slvideo->width, slvideo->height, GST_BUFFER_DATA(buf), - slvideo->format); -#endif + DEBUGMSG("transferring a frame of %dx%d <- %p (%d)", + slvideo->width, slvideo->height, GST_BUFFER_DATA(buf), + slvideo->format); + if (GST_BUFFER_DATA(buf)) { // copy frame and frame info into neutral territory @@ -337,7 +336,7 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, #define MAXDEPTHHACK 4 GST_OBJECT_LOCK(slvideo); - if (slvideo->resize_forced) + if (slvideo->resize_forced_always) // app is giving us a fixed size to work with { gint slwantwidth, slwantheight; slwantwidth = slvideo->resize_try_width; @@ -386,6 +385,8 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, } } + GST_OBJECT_UNLOCK(slvideo); + if (!made_bufferdata_ptr) // need to fallback to malloc at original size { GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK; @@ -394,8 +395,6 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps); } - GST_OBJECT_UNLOCK(slvideo); - *buf = GST_BUFFER_CAST(newbuf); return GST_FLOW_OK; @@ -459,7 +458,7 @@ gst_slvideo_init (GstSLVideo * filter, filter->retained_frame_format = SLV_PF_UNKNOWN; GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS); llgst_caps_replace (&filter->caps, caps); - filter->resize_forced = false; + filter->resize_forced_always = false; filter->resize_try_width = -1; filter->resize_try_height = -1; GST_OBJECT_UNLOCK(filter); @@ -500,7 +499,7 @@ gst_slvideo_get_property (GObject * object, guint prop_id, static gboolean plugin_init (GstPlugin * plugin) { - DEBUGMSG("\n\n\nPLUGIN INIT\n\n\n"); + DEBUGMSG("PLUGIN INIT"); GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin", 0, (gchar*)"Second Life Video Sink"); @@ -528,7 +527,7 @@ void gst_slvideo_init_class (void) "http://www.secondlife.com/"); #undef PACKAGE ll_gst_plugin_register_static (&gst_plugin_desc); - DEBUGMSG(stderr, "\n\n\nCLASS INIT\n\n\n"); + DEBUGMSG("CLASS INIT"); } #endif // LL_GSTREAMER010_ENABLED diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h index 208523e8d0..8f1cf84978 100644 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h +++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h @@ -90,7 +90,7 @@ struct _GstSLVideo int retained_frame_width, retained_frame_height; SLVPixelFormat retained_frame_format; // sticky resize info - bool resize_forced; + bool resize_forced_always; int resize_try_width; int resize_try_height; }; diff --git a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp index d21ff26f83..26173314a7 100644 --- a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp +++ b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp @@ -105,7 +105,7 @@ private: void mouseUp( int x, int y ); void mouseMove( int x, int y ); - bool sizeChanged(); + void sizeChanged(); static bool mDoneInit; @@ -115,13 +115,16 @@ private: int mDepth; - // media natural size + // media NATURAL size int mNaturalWidth; int mNaturalHeight; - int mNaturalRowbytes; - // previous media natural size so we can detect changes - int mPreviousNaturalWidth; - int mPreviousNaturalHeight; + // media current size + int mCurrentWidth; + int mCurrentHeight; + int mCurrentRowbytes; + // previous media size so we can detect changes + int mPreviousWidth; + int mPreviousHeight; // desired render size from host int mWidth; int mHeight; @@ -149,7 +152,7 @@ MediaPluginGStreamer010::MediaPluginGStreamer010( void *host_user_data ) : MediaPluginBase(host_send_func, host_user_data), mBusWatchID ( 0 ), - mNaturalRowbytes ( 4 ), + mCurrentRowbytes ( 4 ), mTextureFormatPrimary ( GL_RGBA ), mTextureFormatType ( GL_UNSIGNED_INT_8_8_8_8_REV ), mSeekWanted(false), @@ -195,6 +198,7 @@ MediaPluginGStreamer010::processGSTEvents(GstBus *bus, } else { + // TODO: grok 'duration' message type DEBUGMSG("Got GST message type: %s", LLGST_MESSAGE_TYPE_NAME (message)); } @@ -429,8 +433,8 @@ MediaPluginGStreamer010::update(int milliseconds) { DEBUGMSG("NEW FRAME READY"); - if (mVideoSink->retained_frame_width != mNaturalWidth || - mVideoSink->retained_frame_height != mNaturalHeight) + if (mVideoSink->retained_frame_width != mCurrentWidth || + mVideoSink->retained_frame_height != mCurrentHeight) // *TODO: also check for change in format { // just resize container, don't consume frame @@ -457,39 +461,38 @@ MediaPluginGStreamer010::update(int milliseconds) GST_OBJECT_UNLOCK(mVideoSink); - mNaturalRowbytes = neww * newd; + mCurrentRowbytes = neww * newd; DEBUGMSG("video container resized to %dx%d", neww, newh); mDepth = newd; - mNaturalWidth = neww; - mNaturalHeight = newh; + mCurrentWidth = neww; + mCurrentHeight = newh; sizeChanged(); return true; } if (mPixels && - mNaturalHeight <= mHeight && - mNaturalWidth <= mWidth && + mCurrentHeight <= mHeight && + mCurrentWidth <= mWidth && !mTextureSegmentName.empty()) { - // we're gonna totally consume this frame - reset 'ready' flag - mVideoSink->retained_frame_ready = FALSE; + mVideoSink->retained_frame_ready = FALSE; int destination_rowbytes = mWidth * mDepth; - for (int row=0; row<mNaturalHeight; ++row) + for (int row=0; row<mCurrentHeight; ++row) { memcpy(&mPixels [destination_rowbytes * row], &mVideoSink->retained_frame_data - [mNaturalRowbytes * row], - mNaturalRowbytes); + [mCurrentRowbytes * row], + mCurrentRowbytes); } GST_OBJECT_UNLOCK(mVideoSink); DEBUGMSG("NEW FRAME REALLY TRULY CONSUMED, TELLING HOST"); - setDirty(0,0,mNaturalWidth,mNaturalHeight); + setDirty(0,0,mCurrentWidth,mCurrentHeight); } else { @@ -836,27 +839,35 @@ MediaPluginGStreamer010::startup() } -bool +void MediaPluginGStreamer010::sizeChanged() { // the shared writing space has possibly changed size/location/whatever - // Check to see whether the movie's natural size has updated - if (mNaturalWidth != mPreviousNaturalWidth || - mNaturalHeight != mPreviousNaturalHeight) + // Check to see whether the movie's NATURAL size has been set yet + if (1 == mNaturalWidth && + 1 == mNaturalHeight) { - mPreviousNaturalWidth = mNaturalWidth; - mPreviousNaturalHeight = mNaturalHeight; + mNaturalWidth = mCurrentWidth; + mNaturalHeight = mCurrentHeight; + DEBUGMSG("Media NATURAL size better detected as %dx%d", + mNaturalWidth, mNaturalHeight); + } + + // if the size has changed then the shm has changed and the app needs telling + if (mCurrentWidth != mPreviousWidth || + mCurrentHeight != mPreviousHeight) + { + mPreviousWidth = mCurrentWidth; + mPreviousHeight = mCurrentHeight; LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); message.setValue("name", mTextureSegmentName); message.setValueS32("width", mNaturalWidth); message.setValueS32("height", mNaturalHeight); - DEBUGMSG("<--- Sending size change request to application with name: '%s' - size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight); + DEBUGMSG("<--- Sending size change request to application with name: '%s' - natural size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight); sendMessage(message); } - - return true; } @@ -941,10 +952,12 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string) // lame to have to decide this now, it depends on the movie. Oh well. mDepth = 4; + mCurrentWidth = 1; + mCurrentHeight = 1; + mPreviousWidth = 1; + mPreviousHeight = 1; mNaturalWidth = 1; mNaturalHeight = 1; - mPreviousNaturalWidth = 1; - mPreviousNaturalHeight = 1; mWidth = 1; mHeight = 1; mTextureWidth = 1; @@ -985,7 +998,6 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string) INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress); mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - } else if(message_name == "shm_remove") { @@ -1064,7 +1076,7 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string) INFOMSG("**** = REAL RESIZE REQUEST FROM APP"); GST_OBJECT_LOCK(mVideoSink); - mVideoSink->resize_forced = true; + mVideoSink->resize_forced_always = true; mVideoSink->resize_try_width = texture_width; mVideoSink->resize_try_height = texture_height; GST_OBJECT_UNLOCK(mVideoSink); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index dbd79f022a..08d3026897 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -158,7 +158,6 @@ set(viewer_SOURCE_FILES llfloaterbuycontents.cpp llfloaterbuycurrency.cpp llfloaterbuyland.cpp - llfloatercall.cpp llfloatercamera.cpp llfloaterchat.cpp llfloaterchatterbox.cpp @@ -201,6 +200,7 @@ set(viewer_SOURCE_FILES llfloaterregioninfo.cpp llfloaterreporter.cpp llfloaterscriptdebug.cpp + llfloaterscriptlimits.cpp llfloatersearch.cpp llfloatersellland.cpp llfloatersettingsdebug.cpp @@ -219,6 +219,7 @@ set(viewer_SOURCE_FILES llfloaterwater.cpp llfloaterwhitelistentry.cpp llfloaterwindlight.cpp + llfloaterwindowsize.cpp llfloaterworldmap.cpp llfolderview.cpp llfolderviewitem.cpp @@ -227,6 +228,7 @@ set(viewer_SOURCE_FILES llgesturemgr.cpp llglsandbox.cpp llgroupactions.cpp + llgroupiconctrl.cpp llgrouplist.cpp llgroupmgr.cpp llhomelocationresponder.cpp @@ -258,7 +260,6 @@ set(viewer_SOURCE_FILES llinventorymodel.cpp llinventoryobserver.cpp llinventorypanel.cpp - llinventorysubtreepanel.cpp lljoystickbutton.cpp lllandmarkactions.cpp lllandmarklist.cpp @@ -302,7 +303,6 @@ set(viewer_SOURCE_FILES lloutputmonitorctrl.cpp lloverlaybar.cpp llpanelavatar.cpp - llpanelavatarrow.cpp llpanelavatartag.cpp llpanelblockedlist.cpp llpanelclassified.cpp @@ -354,6 +354,7 @@ set(viewer_SOURCE_FILES llparticipantlist.cpp llpatchvertexarray.cpp llplacesinventorybridge.cpp + llplacesinventorypanel.cpp llpolymesh.cpp llpolymorph.cpp llpreview.cpp @@ -515,7 +516,6 @@ set(viewer_SOURCE_FILES llvoground.cpp llvoicechannel.cpp llvoiceclient.cpp - llvoicecontrolpanel.cpp llvoiceremotectrl.cpp llvoicevisualizer.cpp llvoinventorylistener.cpp @@ -667,7 +667,6 @@ set(viewer_HEADER_FILES llfloaterbuycontents.h llfloaterbuycurrency.h llfloaterbuyland.h - llfloatercall.h llfloatercamera.h llfloaterchat.h llfloaterchatterbox.h @@ -697,7 +696,7 @@ set(viewer_HEADER_FILES llfloatermediasettings.h llfloatermemleak.h llfloaternamedesc.h - llfloaternearbymedia.h + llfloaternearbymedia.h llfloaternotificationsconsole.h llfloateropenobject.h llfloaterparcel.h @@ -710,6 +709,7 @@ set(viewer_HEADER_FILES llfloaterregioninfo.h llfloaterreporter.h llfloaterscriptdebug.h + llfloaterscriptlimits.h llfloatersearch.h llfloatersellland.h llfloatersettingsdebug.h @@ -727,6 +727,7 @@ set(viewer_HEADER_FILES llfloaterwater.h llfloaterwhitelistentry.h llfloaterwindlight.h + llfloaterwindowsize.h llfloaterworldmap.h llfolderview.h llfoldervieweventlistener.h @@ -735,6 +736,7 @@ set(viewer_HEADER_FILES llfriendcard.h llgesturemgr.h llgroupactions.h + llgroupiconctrl.h llgrouplist.h llgroupmgr.h llhomelocationresponder.h @@ -765,7 +767,6 @@ set(viewer_HEADER_FILES llinventorymodel.h llinventoryobserver.h llinventorypanel.h - llinventorysubtreepanel.h lljoystickbutton.h lllandmarkactions.h lllandmarklist.h @@ -805,7 +806,6 @@ set(viewer_HEADER_FILES lloutputmonitorctrl.h lloverlaybar.h llpanelavatar.h - llpanelavatarrow.h llpanelavatartag.h llpanelblockedlist.h llpanelclassified.h @@ -857,6 +857,7 @@ set(viewer_HEADER_FILES llparticipantlist.h llpatchvertexarray.h llplacesinventorybridge.h + llplacesinventorypanel.h llpolymesh.h llpolymorph.h llpreview.h @@ -1019,7 +1020,6 @@ set(viewer_HEADER_FILES llvoground.h llvoicechannel.h llvoiceclient.h - llvoicecontrolpanel.h llvoiceremotectrl.h llvoicevisualizer.h llvoinventorylistener.h @@ -1396,12 +1396,29 @@ if (WINDOWS) # be met. I'm looking forward to a source-code split-up project next year that will address this kind of thing. # In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py # and have the build deps get tracked *please* tell me about it. + + if(LLKDU_LIBRARY) + # Configure a var for llkdu which may not exist for all builds. + set(LLKDU_DLL_SOURCE ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llkdu.dll) + endif(LLKDU_LIBRARY) + + if(USE_GOOGLE_PERFTOOLS) + # Configure a var for tcmalloc location, if used. + # Note the need to specify multiple names explicitly. + set(GOOGLE_PERF_TOOLS_SOURCE + ${SHARED_LIB_STAGING_DIR}/Release/libtcmalloc_minimal.dll + ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll + ${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll + ) + endif(USE_GOOGLE_PERFTOOLS) + + set(COPY_INPUT_DEPENDECIES # The following commented dependencies are determined at variably at build time. Can't do this here. - #llkdu.dll => llkdu.dll #${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libtcmalloc_minimal.dll => None ... Skipping libtcmalloc_minimal.dll ${CMAKE_SOURCE_DIR}/../etc/message.xml ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg + ${LLKDU_DLL_SOURCE} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llcommon.dll ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libapr-1.dll ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libaprutil-1.dll @@ -1425,6 +1442,7 @@ if (WINDOWS) ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/zlib1.dll ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxplatform.dll ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxoal.dll + ${GOOGLE_PERF_TOOLS_SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/licenses-win32.txt ${CMAKE_CURRENT_SOURCE_DIR}/featuretable.txt ${CMAKE_CURRENT_SOURCE_DIR}/dbghelp.dll @@ -1445,6 +1463,10 @@ if (WINDOWS) ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qmng4.dll ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qsvg4.dll ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qtiff4.dll + ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qcncodecs4.dll + ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecs4.dll + ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecs4.dll + ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecs4.dll ${ARCH_PREBUILT_DIRS_DEBUG}/libeay32.dll ${ARCH_PREBUILT_DIRS_DEBUG}/qtcored4.dll ${ARCH_PREBUILT_DIRS_DEBUG}/qtguid4.dll @@ -1459,6 +1481,10 @@ if (WINDOWS) ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qmngd4.dll ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qsvgd4.dll ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qtiffd4.dll + ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qcncodecsd4.dll + ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecsd4.dll + ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecsd4.dll + ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecsd4.dll SLPlugin media_plugin_quicktime media_plugin_webkit @@ -1492,7 +1518,7 @@ if (WINDOWS) if(LLKDU_LIBRARY) # kdu may not exist! - add_dependencies(${VIEWER_BINARY_NAME} llkdu) + add_dependencies(copy_w_viewer_manifest llkdu) endif(LLKDU_LIBRARY) if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index d94d8bf341..3a6a066ce5 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -265,7 +265,18 @@ <key>Value</key> <real>0.5</real> </map> - <key>AudioSteamingMedia</key> + <key>AudioLevelWind</key> + <map> + <key>Comment</key> + <string>Audio level of wind noise when standing still</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.5</real> + </map> + <key>AudioStreamingMedia</key> <map> <key>Comment</key> <string>Enable streaming</string> @@ -2344,6 +2355,17 @@ <key>Value</key> <string>89556747-24cb-43ed-920b-47caed15465f</string> </map> + <key>DefaultUploadCost</key> + <map> + <key>Comment</key> + <string>Default sound/image/file upload cost(in case economy data is not available).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>10</integer> + </map> <key>DisableCameraConstraints</key> <map> <key>Comment</key> @@ -3224,6 +3246,17 @@ <key>Value</key> <real>0.75</real> </map> + <key>FolderIndentation</key> + <map> + <key>Comment</key> + <string>Number of pixels to indent subfolders in inventory</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>8</integer> + </map> <key>FolderLoadingMessageWaitTime</key> <map> <key>Comment</key> @@ -3585,7 +3618,7 @@ <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> + <string>http://int.searchwww-phx0.damballah.lindenlab.com/viewer/[CATEGORY]?q=[QUERY]&p=[AUTH_TOKEN]&r=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID]</string> </map> <key>HighResSnapshot</key> <map> @@ -8738,6 +8771,17 @@ <key>Value</key> <real>20.0</real> </map> + <key>TextureDecodeDisabled</key> + <map> + <key>Comment</key> + <string>If TRUE, do not fetch and decode any textures</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>TextureDisable</key> <map> <key>Comment</key> @@ -10389,6 +10433,17 @@ <key>Value</key> <string>Default</string> </map> + <key>VoiceParticipantLeftRemoveDelay</key> + <map> + <key>Comment</key> + <string>Timeout to remove participants who has left Voice chat from the list in Voice Controls Panel</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>10</integer> + </map> <key>VoicePort</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl index 28908a311d..0fad5b4b50 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl @@ -10,7 +10,6 @@ uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; uniform sampler2DRect lightMap; -uniform sampler2DRect edgeMap; uniform float dist_factor; uniform float blur_size; @@ -46,53 +45,36 @@ void main() dlt /= max(-pos.z*dist_factor, 1.0); - vec2 defined_weight = kern[0].xy; // special case the kern[0] (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' + vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' vec4 col = defined_weight.xyxx * ccol; - - float center_e = 1.0 - (texture2DRect(edgeMap, vary_fragcoord.xy).a+ - texture2DRect(edgeMap, vary_fragcoord.xy+dlt*0.333).a+ - texture2DRect(edgeMap, vary_fragcoord.xy-dlt*0.333).a); - float e = center_e; for (int i = 1; i < 4; i++) { vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; - - e = max(e, 0.0); - - vec2 wght = kern[i].xy*e; - - col += texture2DRect(lightMap, tc)*wght.xyxx; - defined_weight += wght; - - e *= e; - e -= texture2DRect(edgeMap, tc.xy).a+ - texture2DRect(edgeMap, tc.xy+dlt*0.333).a+ - texture2DRect(edgeMap, tc.xy-dlt*0.333).a; + vec3 samppos = getPosition(tc).xyz; + float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane + if (d*d <= 0.003) + { + col += texture2DRect(lightMap, tc)*kern[i].xyxx; + defined_weight += kern[i].xy; + } } - - e = center_e; for (int i = 1; i < 4; i++) { vec2 tc = vary_fragcoord.xy - kern[i].z*dlt; - - e = max(e, 0.0); - - vec2 wght = kern[i].xy*e; - - col += texture2DRect(lightMap, tc)*wght.xyxx; - defined_weight += wght; - - e *= e; - e -= texture2DRect(edgeMap, tc.xy).a+ - texture2DRect(edgeMap, tc.xy+dlt*0.333).a+ - texture2DRect(edgeMap, tc.xy-dlt*0.333).a; + vec3 samppos = getPosition(tc).xyz; + float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane + if (d*d <= 0.003) + { + col += texture2DRect(lightMap, tc)*kern[i].xyxx; + defined_weight += kern[i].xy; + } } + col /= defined_weight.xyxx; gl_FragColor = col; - - //gl_FragColor = ccol; } + diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index ae89eb4413..448e20b382 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -5608,9 +5608,7 @@ <layer_set body_region="head" width="512" - height="512" - clear_alpha="false" - alpha_tga_file="head_alpha.tga"> + height="512"> <layer name="head bump base" fixed_color = "128,128,128,255" @@ -6609,6 +6607,13 @@ render_pass="bump"> local_texture="head_bodypaint" /> </layer> <layer + name="eyelash alpha" + visibility_mask="TRUE"> + <texture + tga_file="head_alpha.tga" + file_is_mask="TRUE" /> + </layer> + <layer name="head alpha" visibility_mask="TRUE"> <texture @@ -6620,6 +6625,7 @@ render_pass="bump"> local_texture="head_tattoo" /> </layer> + </layer_set> <!-- =========================================================== --> diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index d20c23df80..4029bf95a0 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,4 +1,4 @@ -version 20 +version 21 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences // Should be combined into one table @@ -28,6 +28,7 @@ RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 RenderAvatarVP 1 1 RenderCubeMap 1 1 +RenderDelayVBUpdate 1 0 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderFogRatio 1 4.0 diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index 57d712ede7..61a8e51c50 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -1,4 +1,4 @@ -version 20 +version 21 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences // Should be combined into one table @@ -28,6 +28,7 @@ RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 RenderAvatarVP 1 1 RenderCubeMap 1 1 +RenderDelayVBUpdate 1 0 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderFogRatio 1 4.0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 15974c0691..12d47a904c 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -1,4 +1,4 @@ -version 20 +version 21 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences // Should be combined into one table @@ -28,6 +28,7 @@ RenderAvatarCloth 0 0 RenderAvatarLODFactor 1 1.0 RenderAvatarVP 1 0 RenderCubeMap 1 1 +RenderDelayVBUpdate 1 0 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderFogRatio 1 4.0 diff --git a/indra/newview/gpu_table.txt b/indra/newview/gpu_table.txt index 5c5c4e5b3c..cc8f6780e3 100644 --- a/indra/newview/gpu_table.txt +++ b/indra/newview/gpu_table.txt @@ -157,7 +157,7 @@ Intel Bear Lake .*Intel.*Bear Lake.* 0 0 Intel Broadwater .*Intel.*Broadwater.* 0 0 Intel Brookdale .*Intel.*Brookdale.* 0 0 Intel Cantiga .*Intel.*Cantiga.* 0 0 -Intel Eaglelake .*Intel.*Eaglelake.* 0 0 +Intel Eaglelake .*Intel.*Eaglelake.* 0 1 Intel Montara .*Intel.*Montara.* 0 0 Intel Springdale .*Intel.*Springdale.* 0 0 Matrox .*Matrox.* 0 0 diff --git a/indra/newview/linux_tools/register_secondlifeprotocol.sh b/indra/newview/linux_tools/register_secondlifeprotocol.sh index c7b4d55461..16e73cb854 100755 --- a/indra/newview/linux_tools/register_secondlifeprotocol.sh +++ b/indra/newview/linux_tools/register_secondlifeprotocol.sh @@ -22,13 +22,12 @@ else fi # Register handler for KDE-aware apps -if [ -z "$KDEHOME" ]; then - KDEHOME=~/.kde -fi -LLKDEPROTDIR=${KDEHOME}/share/services -if [ -d "$LLKDEPROTDIR" ]; then - LLKDEPROTFILE=${LLKDEPROTDIR}/secondlife.protocol - cat > ${LLKDEPROTFILE} <<EOF || echo Warning: Did not register secondlife:// handler with KDE: Could not write ${LLKDEPROTFILE} +for LLKDECONFIG in kde-config kde4-config; do + if [ `which $LLKDECONFIG` ]; then + LLKDEPROTODIR=`$LLKDECONFIG --path services | cut -d ':' -f 1` + if [ -d "$LLKDEPROTODIR" ]; then + LLKDEPROTOFILE=${LLKDEPROTODIR}/secondlife.protocol + cat > ${LLKDEPROTOFILE} <<EOF || echo Warning: Did not register secondlife:// handler with KDE: Could not write ${LLKDEPROTOFILE} [Protocol] exec=${HANDLER} '%u' protocol=secondlife @@ -41,6 +40,9 @@ writing=false makedir=false deleting=false EOF -else - echo Warning: Did not register secondlife:// handler with KDE: Directory $LLKDEPROTDIR does not exist. -fi + else + echo Warning: Did not register secondlife:// handler with KDE: Directory $LLKDEPROTODIR does not exist. + fi + fi +done + diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 628982973c..d2a56f65dd 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -747,7 +747,12 @@ void LLAgent::setFlying(BOOL fly) { if (mAvatarObject.notNull()) { - if(mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_STANDUP) != mAvatarObject->mSignaledAnimations.end()) + // *HACK: Don't allow to start the flying mode if we got ANIM_AGENT_STANDUP signal + // because in this case we won't get a signal to start avatar flying animation and + // it will be walking with flying mode "ON" indication. However we allow to switch + // the flying mode off if we get ANIM_AGENT_STANDUP signal. See process_avatar_animation(). + // See EXT-2781. + if(fly && mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_STANDUP) != mAvatarObject->mSignaledAnimations.end()) { return; } diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 454e547155..d21965568d 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -100,6 +100,7 @@ public: LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false) {} ~LLLibraryOutfitsFetch() {} virtual void done(); + void doneIdle(); protected: void folderDone(void); void outfitsDone(void); @@ -115,6 +116,39 @@ BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE; using namespace LLVOAvatarDefines; +// HACK: For EXT-3923: Pants item shows in inventory with skin icon and messes with "current look" +// Some db items are corrupted, have inventory flags = 0, implying wearable type = shape, even though +// wearable type stored in asset is some other value. +// Calling this function whenever a wearable is added to increase visibility if this problem +// turns up in other inventories. +void checkWearableAgainstInventory(LLWearable *wearable) +{ + if (wearable->getItemID().isNull()) + return; + + // Check for wearable type consistent with inventory item wearable type. + LLViewerInventoryItem *item = gInventory.getItem(wearable->getItemID()); + if (item) + { + if (!item->isWearableType()) + { + llwarns << "wearable associated with non-wearable item" << llendl; + } + if (item->getWearableType() != wearable->getType()) + { + llwarns << "type mismatch: wearable " << wearable->getName() + << " has type " << wearable->getType() + << " but inventory item " << item->getName() + << " has type " << item->getWearableType() << llendl; + } + } + else + { + llwarns << "wearable inventory item not found" << wearable->getName() + << " itemID " << wearable->getItemID().asString() << llendl; + } +} + void LLAgentWearables::dump() { llinfos << "LLAgentWearablesDump" << llendl; @@ -656,6 +690,7 @@ LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index) void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearable *wearable) { + LLWearable *old_wearable = getWearable(type,index); if (!old_wearable) { @@ -679,6 +714,7 @@ void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearab wearable_vec[index] = wearable; old_wearable->setLabelUpdated(); wearableUpdated(wearable); + checkWearableAgainstInventory(wearable); } } @@ -694,6 +730,7 @@ U32 LLAgentWearables::pushWearable(const EWearableType type, LLWearable *wearabl { mWearableDatas[type].push_back(wearable); wearableUpdated(wearable); + checkWearableAgainstInventory(wearable); return mWearableDatas[type].size()-1; } return MAX_WEARABLES_PER_TYPE; @@ -871,24 +908,31 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs if (mInitialWearablesUpdateReceived) return; mInitialWearablesUpdateReceived = true; + + // If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account) + // then auto-populate outfits from the library into the My Outfits folder. + if (LLInventoryModel::getIsFirstTimeInViewer2()) + { + gAgentWearables.populateMyOutfitsFolder(); + } LLUUID agent_id; gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); - const BOOL is_first_time_in_viewer2_0 = (gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) == LLUUID::null); - - LLVOAvatar* avatar = gAgent.getAvatarObject(); if (avatar && (agent_id == avatar->getID())) { gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgentQueryManager.mUpdateSerialNum); + const S32 NUM_BODY_PARTS = 4; S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData); - if (num_wearables < 4) + if (num_wearables < NUM_BODY_PARTS) { // Transitional state. Avatars should always have at least their body parts (hair, eyes, shape and skin). - // The fact that they don't have any here (only a dummy is sent) implies that this account existed - // before we had wearables, or that the database has gotten messed up. + // The fact that they don't have any here (only a dummy is sent) implies that either: + // 1. This account existed before we had wearables + // 2. The database has gotten messed up + // 3. This is the account's first login (i.e. the wearables haven't been generated yet). return; } @@ -957,8 +1001,6 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs gInventory.addObserver(outfit); } - if (is_first_time_in_viewer2_0) - gAgentWearables.populateMyOutfitsFolder(); } } @@ -1354,6 +1396,7 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name) LLPointer<LLInventoryCallback> cb = new LLAutoRenameFolder(folder_id); LLAppearanceManager::instance().shallowCopyCategory(LLAppearanceManager::instance().getCOF(),folder_id, cb); + LLAppearanceManager::instance().createBaseOutfitLink(folder_id, NULL); return folder_id; } @@ -1699,6 +1742,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n mWearableDatas[type].push_back(new_wearable); llinfos << "Added additional wearable for type " << type << " size is now " << mWearableDatas[type].size() << llendl; + checkWearableAgainstInventory(new_wearable); } else { @@ -2079,51 +2123,50 @@ void LLAgentWearables::populateMyOutfitsFolder(void) { LLLibraryOutfitsFetch* outfits = new LLLibraryOutfitsFetch(); - // What we do here is get the complete information on the items in - // the inventory, and set up an observer that will wait for that to - // happen. + // Get the complete information on the items in the inventory and + // setup an observer that will wait for that to happen. LLInventoryFetchDescendentsObserver::folder_ref_t folders; const LLUUID my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); folders.push_back(my_outfits_id); + gInventory.addObserver(outfits); outfits->fetchDescendents(folders); - if(outfits->isEverythingComplete()) - { - // everything is already here - call done. - outfits->done(); - } - else - { - // it's all on it's way - add an observer, and the inventory - // will call done for us when everything is here. - gInventory.addObserver(outfits); - } } void LLLibraryOutfitsFetch::done() { - switch (mCurrFetchStep){ + // Delay this until idle() routine, since it's a heavy operation and + // we also can't have it run within notifyObservers. + doOnIdle(boost::bind(&LLLibraryOutfitsFetch::doneIdle,this)); + gInventory.removeObserver(this); // Prevent doOnIdle from being added twice. +} + +void LLLibraryOutfitsFetch::doneIdle() +{ + gInventory.addObserver(this); // Add this back in since it was taken out during ::done() + switch (mCurrFetchStep) + { case LOFS_FOLDER: - mCurrFetchStep = LOFS_OUTFITS; folderDone(); break; case LOFS_OUTFITS: - mCurrFetchStep = LOFS_CONTENTS; outfitsDone(); break; case LOFS_CONTENTS: - // No longer need this observer hanging around. - gInventory.removeObserver(this); contentsDone(); break; default: - gInventory.removeObserver(this); - delete this; - return; + llwarns << "Got invalid state for outfit fetch: " << mCurrFetchStep << llendl; + mOutfitsPopulated = TRUE; + break; } + + // We're completely done. Cleanup. if (mOutfitsPopulated) { + gInventory.removeObserver(this); delete this; + return; } } @@ -2137,7 +2180,6 @@ void LLLibraryOutfitsFetch::folderDone(void) if (cat_array.count() > 0 || wearable_array.count() > 0) { mOutfitsPopulated = true; - gInventory.removeObserver(this); return; } @@ -2146,17 +2188,11 @@ void LLLibraryOutfitsFetch::folderDone(void) mCompleteFolders.clear(); - // What we do here is get the complete information on the items in - // the inventory, and set up an observer that will wait for that to - // happen. + // Get the complete information on the items in the inventory. LLInventoryFetchDescendentsObserver::folder_ref_t folders; folders.push_back(library_clothing_id); + mCurrFetchStep = LOFS_OUTFITS; fetchDescendents(folders); - if(isEverythingComplete()) - { - // everything is already here - call done. - outfitsDone(); - } } void LLLibraryOutfitsFetch::outfitsDone(void) @@ -2167,20 +2203,23 @@ void LLLibraryOutfitsFetch::outfitsDone(void) LLInventoryModel::EXCLUDE_TRASH); LLInventoryFetchDescendentsObserver::folder_ref_t folders; - for(S32 i = 0; i < cat_array.count(); ++i) + + llassert(cat_array.count() > 0); + for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); + iter != cat_array.end(); + ++iter) { - if (cat_array.get(i)->getName() != "More Outfits" && cat_array.get(i)->getName() != "Ruth"){ - folders.push_back(cat_array.get(i)->getUUID()); - mOutfits.push_back( std::make_pair(cat_array.get(i)->getUUID(), cat_array.get(i)->getName() )); + const LLViewerInventoryCategory *cat = iter->get(); + if (cat->getName() != "More Outfits" && cat->getName() != "Ruth") + { + folders.push_back(cat->getUUID()); + mOutfits.push_back(std::make_pair(cat->getUUID(), cat->getName())); } } mCompleteFolders.clear(); + + mCurrFetchStep = LOFS_CONTENTS; fetchDescendents(folders); - if(isEverythingComplete()) - { - // everything is already here - call done. - contentsDone(); - } } void LLLibraryOutfitsFetch::contentsDone(void) @@ -2192,9 +2231,7 @@ void LLLibraryOutfitsFetch::contentsDone(void) LLUUID folder_id = gInventory.createNewCategory(parent_id, LLFolderType::FT_OUTFIT, mOutfits[i].second); - LLAppearanceManager::getInstance()->shallowCopyCategory(mOutfits[i].first, folder_id, NULL); - gInventory.notifyObservers(); } mOutfitsPopulated = true; } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 43b2f34ecd..25f1accb22 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -364,7 +364,7 @@ LLUUID LLAppearanceManager::getCOF() } -const LLViewerInventoryItem* LLAppearanceManager::getCurrentOutfitLink() +const LLViewerInventoryItem* LLAppearanceManager::getBaseOutfitLink() { const LLUUID& current_outfit_cat = getCOF(); LLInventoryModel::cat_array_t cat_array; @@ -444,6 +444,28 @@ void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID } } +void LLAppearanceManager::purgeBaseOutfitLink(const LLUUID& category) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(category, cats, items, + LLInventoryModel::EXCLUDE_TRASH); + for (S32 i = 0; i < items.count(); ++i) + { + LLViewerInventoryItem *item = items.get(i); + if (item->getActualType() != LLAssetType::AT_LINK_FOLDER) + continue; + if (item->getIsLinkType()) + { + LLViewerInventoryCategory* catp = item->getLinkedCategory(); + if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) + { + gInventory.purgeObject(item->getUUID()); + } + } + } +} + void LLAppearanceManager::purgeCategory(const LLUUID& category, bool keep_outfit_links) { LLInventoryModel::cat_array_t cats; @@ -578,17 +600,9 @@ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append) linkAll(cof, gest_items, link_waiter); // Add link to outfit if category is an outfit. - LLViewerInventoryCategory* catp = gInventory.getCategory(category); if (!append) { - std::string new_outfit_name = ""; - if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) - { - link_inventory_item(gAgent.getID(), category, cof, catp->getName(), - LLAssetType::AT_LINK_FOLDER, link_waiter); - new_outfit_name = catp->getName(); - } - updatePanelOutfitName(new_outfit_name); + createBaseOutfitLink(category, link_waiter); } } @@ -602,6 +616,22 @@ void LLAppearanceManager::updatePanelOutfitName(const std::string& name) } } +void LLAppearanceManager::createBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> link_waiter) +{ + const LLUUID cof = getCOF(); + LLViewerInventoryCategory* catp = gInventory.getCategory(category); + std::string new_outfit_name = ""; + + purgeBaseOutfitLink(cof); + + if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) + { + link_inventory_item(gAgent.getID(), category, cof, catp->getName(), + LLAssetType::AT_LINK_FOLDER, link_waiter); + new_outfit_name = catp->getName(); + } + updatePanelOutfitName(new_outfit_name); +} void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder, bool append) { diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index b625d42a50..11b910ee11 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -62,11 +62,13 @@ public: LLUUID getCOF(); // Finds the folder link to the currently worn outfit - const LLViewerInventoryItem *getCurrentOutfitLink(); + const LLViewerInventoryItem *getBaseOutfitLink(); // Update the displayed outfit name in UI. void updatePanelOutfitName(const std::string& name); + void createBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> link_waiter); + void updateAgentWearables(LLWearableHoldingPattern* holder, bool append); // For debugging - could be moved elsewhere. @@ -114,6 +116,7 @@ private: bool follow_folder_links); void purgeCategory(const LLUUID& category, bool keep_outfit_links); + void purgeBaseOutfitLink(const LLUUID& category); std::set<LLUUID> mRegisteredAttachments; bool mAttachmentInvLinkEnabled; diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index c5a1ffdcb3..2a8c55e5db 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -243,7 +243,6 @@ void LLAvatarActions::startAdhocCall(const std::vector<LLUUID>& ids) return; } - // start the call once the session has fully initialized gIMMgr->autoStartCallOnStartup(session_id); make_ui_sound("UISndStartIM"); @@ -333,6 +332,54 @@ void LLAvatarActions::pay(const LLUUID& id) } } +// static +void LLAvatarActions::kick(const LLUUID& id) +{ + LLSD payload; + payload["avatar_id"] = id; + LLNotifications::instance().add("KickUser", LLSD(), payload, handleKick); +} + +// static +void LLAvatarActions::freeze(const LLUUID& id) +{ + LLSD payload; + payload["avatar_id"] = id; + LLNotifications::instance().add("FreezeUser", LLSD(), payload, handleFreeze); +} + +// static +void LLAvatarActions::unfreeze(const LLUUID& id) +{ + LLSD payload; + payload["avatar_id"] = id; + LLNotifications::instance().add("UnFreezeUser", LLSD(), payload, handleUnfreeze); +} + +//static +void LLAvatarActions::csr(const LLUUID& id, std::string name) +{ + if (name.empty()) return; + + std::string url = "http://csr.lindenlab.com/agent/"; + + // slow and stupid, but it's late + S32 len = name.length(); + for (S32 i = 0; i < len; i++) + { + if (name[i] == ' ') + { + url += "%20"; + } + else + { + url += name[i]; + } + } + + LLWeb::loadURL(url); +} + //static void LLAvatarActions::share(const LLUUID& id) { @@ -457,6 +504,67 @@ bool LLAvatarActions::callbackAddFriendWithMessage(const LLSD& notification, con } // static +bool LLAvatarActions::handleKick(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + + if (option == 0) + { + LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); + LLMessageSystem* msg = gMessageSystem; + + msg->newMessageFast(_PREHASH_GodKickUser); + msg->nextBlockFast(_PREHASH_UserInfo); + msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_AgentID, avatar_id ); + msg->addU32("KickFlags", KICK_FLAGS_DEFAULT ); + msg->addStringFast(_PREHASH_Reason, response["message"].asString() ); + gAgent.sendReliableMessage(); + } + return false; +} +bool LLAvatarActions::handleFreeze(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + + if (option == 0) + { + LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); + LLMessageSystem* msg = gMessageSystem; + + msg->newMessageFast(_PREHASH_GodKickUser); + msg->nextBlockFast(_PREHASH_UserInfo); + msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_AgentID, avatar_id ); + msg->addU32("KickFlags", KICK_FLAGS_FREEZE ); + msg->addStringFast(_PREHASH_Reason, response["message"].asString() ); + gAgent.sendReliableMessage(); + } + return false; +} +bool LLAvatarActions::handleUnfreeze(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + std::string text = response["message"].asString(); + if (option == 0) + { + LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); + LLMessageSystem* msg = gMessageSystem; + + msg->newMessageFast(_PREHASH_GodKickUser); + msg->nextBlockFast(_PREHASH_UserInfo); + msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_AgentID, avatar_id ); + msg->addU32("KickFlags", KICK_FLAGS_UNFREEZE ); + msg->addStringFast(_PREHASH_Reason, text ); + gAgent.sendReliableMessage(); + } + return false; +} +// static bool LLAvatarActions::callbackAddFriend(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 01c18d4228..a4504ae679 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -138,11 +138,35 @@ public: */ static void inviteToGroup(const LLUUID& id); + /** + * Kick avatar off grid + */ + static void kick(const LLUUID& id); + + /** + * Freeze avatar + */ + static void freeze(const LLUUID& id); + + /** + * Unfreeze avatar + */ + static void unfreeze(const LLUUID& id); + + /** + * Open csr page for avatar + */ + static void csr(const LLUUID& id, std::string name); + + private: static bool callbackAddFriend(const LLSD& notification, const LLSD& response); static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response); static bool handleRemove(const LLSD& notification, const LLSD& response); static bool handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id); + static bool handleKick(const LLSD& notification, const LLSD& response); + static bool handleFreeze(const LLSD& notification, const LLSD& response); + static bool handleUnfreeze(const LLSD& notification, const LLSD& response); static void callback_invite_to_group(LLUUID group_id, LLUUID id); // Just request friendship, no dialog. diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 44cbbbb6b2..42ae122ff9 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -38,7 +38,6 @@ #include "llavatarconstants.h" #include "llcallingcard.h" // for LLAvatarTracker #include "llavataractions.h" -#include "llimview.h" #include "llmenugl.h" #include "lluictrlfactory.h" diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 71b23e1383..5df73a994e 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -33,7 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llavatarlist.h" -#include "llagent.h" // for comparator +#include "llagentdata.h" // for comparator // newview #include "llcallingcard.h" // for LLAvatarTracker @@ -51,6 +51,12 @@ static const F32 LIT_UPDATE_PERIOD = 5; // Used to limit time spent for avatar list update per frame. static const unsigned ADD_LIMIT = 50; +bool LLAvatarList::contains(const LLUUID& id) +{ + const uuid_vector_t& ids = getIDs(); + return std::find(ids.begin(), ids.end(), id) != ids.end(); +} + void LLAvatarList::toggleIcons() { // Save the new value for new items to use. @@ -159,6 +165,7 @@ void LLAvatarList::clear() { getIDs().clear(); setDirty(true); + LLFlatListView::clear(); } void LLAvatarList::setNameFilter(const std::string& filter) @@ -322,7 +329,6 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is item->setAvatarId(id, mIgnoreOnlineStatus); item->setOnline(mIgnoreOnlineStatus ? true : is_online); item->showLastInteractionTime(mShowLastInteractionTime); - item->setContextMenu(mContextMenu); item->childSetVisible("info_btn", false); item->setAvatarIconVisible(mShowIcons); @@ -425,11 +431,11 @@ bool LLAvatarItemAgentOnTopComparator::doCompare(const LLAvatarListItem* avatar_ { //keep agent on top, if first is agent, //then we need to return true to elevate this id, otherwise false. - if(avatar_item1->getAvatarId() == gAgent.getID()) + if(avatar_item1->getAvatarId() == gAgentID) { return true; } - else if (avatar_item2->getAvatarId() == gAgent.getID()) + else if (avatar_item2->getAvatarId() == gAgentID) { return false; } diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index e913be0f62..0d2ce884ae 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -75,6 +75,7 @@ public: void setNameFilter(const std::string& filter); void setDirty(bool val = true) { mDirty = val; } uuid_vector_t& getIDs() { return mIDs; } + bool contains(const LLUUID& id); void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; } diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 072eebdf2d..6945ac6932 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -43,6 +43,12 @@ #include "lltextutil.h" #include "llbutton.h" +bool LLAvatarListItem::sStaticInitialized = false; +S32 LLAvatarListItem::sIconWidth = 0; +S32 LLAvatarListItem::sInfoBtnWidth = 0; +S32 LLAvatarListItem::sProfileBtnWidth = 0; +S32 LLAvatarListItem::sSpeakingIndicatorWidth = 0; + LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/) : LLPanel(), mAvatarIcon(NULL), @@ -51,7 +57,6 @@ LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/) mSpeakingIndicator(NULL), mInfoBtn(NULL), mProfileBtn(NULL), - mContextMenu(NULL), mOnlineStatus(E_UNKNOWN), mShowInfoBtn(true), mShowProfileBtn(true) @@ -88,10 +93,15 @@ BOOL LLAvatarListItem::postBuild() // Remember avatar icon width including its padding from the name text box, // so that we can hide and show the icon again later. - mIconWidth = mAvatarName->getRect().mLeft - mAvatarIcon->getRect().mLeft; - mInfoBtnWidth = mInfoBtn->getRect().mRight - mSpeakingIndicator->getRect().mRight; - mProfileBtnWidth = mProfileBtn->getRect().mRight - mInfoBtn->getRect().mRight; - mSpeakingIndicatorWidth = mSpeakingIndicator->getRect().mRight - mAvatarName->getRect().mRight; + if (!sStaticInitialized) + { + sIconWidth = mAvatarName->getRect().mLeft - mAvatarIcon->getRect().mLeft; + sInfoBtnWidth = mInfoBtn->getRect().mRight - mSpeakingIndicator->getRect().mRight; + sProfileBtnWidth = mProfileBtn->getRect().mRight - mInfoBtn->getRect().mRight; + sSpeakingIndicatorWidth = mSpeakingIndicator->getRect().mRight - mAvatarName->getRect().mRight; + + sStaticInitialized = true; + } /* if(!p.buttons.profile) @@ -148,7 +158,6 @@ void LLAvatarListItem::changed(U32 mask) void LLAvatarListItem::setOnline(bool online) { // *FIX: setName() overrides font style set by setOnline(). Not an issue ATM. - // *TODO: Make the colors configurable via XUI. if (mOnlineStatus != E_UNKNOWN && (bool) mOnlineStatus == online) return; @@ -156,11 +165,7 @@ void LLAvatarListItem::setOnline(bool online) mOnlineStatus = (EOnlineStatus) online; // Change avatar name font style depending on the new online status. - mAvatarNameStyle.color = online ? LLColor4::white : LLColor4::grey; - setNameInternal(mAvatarName->getText(), mHighlihtSubstring); - - // Make the icon fade if the avatar goes offline. - mAvatarIcon->setColor(online ? LLColor4::white : LLColor4::smoke); + setState(online ? IS_ONLINE : IS_OFFLINE); } void LLAvatarListItem::setName(const std::string& name) @@ -173,6 +178,21 @@ void LLAvatarListItem::setHighlight(const std::string& highlight) setNameInternal(mAvatarName->getText(), mHighlihtSubstring = highlight); } +void LLAvatarListItem::setState(EItemState item_style) +{ + item_style_map_t& item_styles_params_map = getItemStylesParams(); + + mAvatarNameStyle = item_styles_params_map[item_style]; + + // *NOTE: You cannot set the style on a text box anymore, you must + // rebuild the text. This will cause problems if the text contains + // hyperlinks, as their styles will be wrong. + setNameInternal(mAvatarName->getText(), mHighlihtSubstring); + + icon_color_map_t& item_icon_color_map = getItemIconColorMap(); + mAvatarIcon->setColor(item_icon_color_map[item_style]); +} + void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes) { if (mAvatarId.notNull()) @@ -214,7 +234,7 @@ void LLAvatarListItem::setShowInfoBtn(bool show) if(mShowInfoBtn == show) return; mShowInfoBtn = show; - S32 width_delta = show ? - mInfoBtnWidth : mInfoBtnWidth; + S32 width_delta = show ? - sInfoBtnWidth : sInfoBtnWidth; //Translating speaking indicator mSpeakingIndicator->translate(width_delta, 0); @@ -228,7 +248,7 @@ void LLAvatarListItem::setShowProfileBtn(bool show) if(mShowProfileBtn == show) return; mShowProfileBtn = show; - S32 width_delta = show ? - mProfileBtnWidth : mProfileBtnWidth; + S32 width_delta = show ? - sProfileBtnWidth : sProfileBtnWidth; //Translating speaking indicator mSpeakingIndicator->translate(width_delta, 0); @@ -242,7 +262,7 @@ void LLAvatarListItem::setSpeakingIndicatorVisible(bool visible) if (mSpeakingIndicator->getVisible() == (BOOL)visible) return; mSpeakingIndicator->setVisible(visible); - S32 width_delta = visible ? - mSpeakingIndicatorWidth : mSpeakingIndicatorWidth; + S32 width_delta = visible ? - sSpeakingIndicatorWidth : sSpeakingIndicatorWidth; //Reshaping avatar name mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight()); @@ -259,7 +279,7 @@ void LLAvatarListItem::setAvatarIconVisible(bool visible) // Move the avatar name horizontally by icon size + its distance from the avatar name. LLRect name_rect = mAvatarName->getRect(); - name_rect.mLeft += visible ? mIconWidth : -mIconWidth; + name_rect.mLeft += visible ? sIconWidth : -sIconWidth; mAvatarName->setRect(name_rect); } @@ -327,10 +347,10 @@ void LLAvatarListItem::onNameCache(const std::string& first_name, const std::str void LLAvatarListItem::reshapeAvatarName() { S32 width_delta = 0; - width_delta += mShowProfileBtn ? mProfileBtnWidth : 0; - width_delta += mSpeakingIndicator->getVisible() ? mSpeakingIndicatorWidth : 0; - width_delta += mAvatarIcon->getVisible() ? mIconWidth : 0; - width_delta += mShowInfoBtn ? mInfoBtnWidth : 0; + width_delta += mShowProfileBtn ? sProfileBtnWidth : 0; + width_delta += mSpeakingIndicator->getVisible() ? sSpeakingIndicatorWidth : 0; + width_delta += mAvatarIcon->getVisible() ? sIconWidth : 0; + width_delta += mShowInfoBtn ? sInfoBtnWidth : 0; width_delta += mLastInteractionTime->getVisible() ? mLastInteractionTime->getRect().getWidth() : 0; S32 height = mAvatarName->getRect().getHeight(); @@ -386,3 +406,90 @@ std::string LLAvatarListItem::formatSeconds(U32 secs) args["[COUNT]"] = llformat("%u", count); return getString(fmt, args); } + +// static +LLAvatarListItem::item_style_map_t& LLAvatarListItem::getItemStylesParams() +{ + static item_style_map_t item_styles_params_map; + if (!item_styles_params_map.empty()) return item_styles_params_map; + + LLPanel::Params params = LLUICtrlFactory::getDefaultParams<LLPanel>(); + LLPanel* params_panel = LLUICtrlFactory::create<LLPanel>(params); + + BOOL sucsess = LLUICtrlFactory::instance().buildPanel(params_panel, "panel_avatar_list_item_params.xml"); + + if (sucsess) + { + + item_styles_params_map.insert( + std::make_pair(IS_DEFAULT, + params_panel->getChild<LLTextBox>("default_style")->getDefaultStyle())); + + item_styles_params_map.insert( + std::make_pair(IS_VOICE_INVITED, + params_panel->getChild<LLTextBox>("voice_call_invited_style")->getDefaultStyle())); + + item_styles_params_map.insert( + std::make_pair(IS_VOICE_JOINED, + params_panel->getChild<LLTextBox>("voice_call_joined_style")->getDefaultStyle())); + + item_styles_params_map.insert( + std::make_pair(IS_VOICE_LEFT, + params_panel->getChild<LLTextBox>("voice_call_left_style")->getDefaultStyle())); + + item_styles_params_map.insert( + std::make_pair(IS_ONLINE, + params_panel->getChild<LLTextBox>("online_style")->getDefaultStyle())); + + item_styles_params_map.insert( + std::make_pair(IS_OFFLINE, + params_panel->getChild<LLTextBox>("offline_style")->getDefaultStyle())); + } + else + { + item_styles_params_map.insert(std::make_pair(IS_DEFAULT, LLStyle::Params())); + item_styles_params_map.insert(std::make_pair(IS_VOICE_INVITED, LLStyle::Params())); + item_styles_params_map.insert(std::make_pair(IS_VOICE_JOINED, LLStyle::Params())); + item_styles_params_map.insert(std::make_pair(IS_VOICE_LEFT, LLStyle::Params())); + item_styles_params_map.insert(std::make_pair(IS_ONLINE, LLStyle::Params())); + item_styles_params_map.insert(std::make_pair(IS_OFFLINE, LLStyle::Params())); + } + if (params_panel) params_panel->die(); + + return item_styles_params_map; +} + +// static +LLAvatarListItem::icon_color_map_t& LLAvatarListItem::getItemIconColorMap() +{ + static icon_color_map_t item_icon_color_map; + if (!item_icon_color_map.empty()) return item_icon_color_map; + + item_icon_color_map.insert( + std::make_pair(IS_DEFAULT, + LLUIColorTable::instance().getColor("AvatarListItemIconDefaultColor", LLColor4::white))); + + item_icon_color_map.insert( + std::make_pair(IS_VOICE_INVITED, + LLUIColorTable::instance().getColor("AvatarListItemIconVoiceInvitedColor", LLColor4::white))); + + item_icon_color_map.insert( + std::make_pair(IS_VOICE_JOINED, + LLUIColorTable::instance().getColor("AvatarListItemIconVoiceJoinedColor", LLColor4::white))); + + item_icon_color_map.insert( + std::make_pair(IS_VOICE_LEFT, + LLUIColorTable::instance().getColor("AvatarListItemIconVoiceLeftColor", LLColor4::white))); + + item_icon_color_map.insert( + std::make_pair(IS_ONLINE, + LLUIColorTable::instance().getColor("AvatarListItemIconOnlineColor", LLColor4::white))); + + item_icon_color_map.insert( + std::make_pair(IS_OFFLINE, + LLUIColorTable::instance().getColor("AvatarListItemIconOfflineColor", LLColor4::white))); + + return item_icon_color_map; +} + +// EOF diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index aa1b7593f5..96097bc9b5 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -46,6 +46,15 @@ class LLAvatarIconCtrl; class LLAvatarListItem : public LLPanel, public LLFriendObserver { public: + typedef enum e_item_state_type { + IS_DEFAULT, + IS_VOICE_INVITED, + IS_VOICE_JOINED, + IS_VOICE_LEFT, + IS_ONLINE, + IS_OFFLINE, + } EItemState; + class ContextMenu { public: @@ -73,6 +82,7 @@ public: void setOnline(bool online); void setName(const std::string& name); void setHighlight(const std::string& highlight); + void setState(EItemState item_style); void setAvatarId(const LLUUID& id, bool ignore_status_changes = false); void setLastInteractionTime(U32 secs_since); //Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly @@ -91,8 +101,6 @@ public: void showInfoBtn(bool show_info_btn) {mInfoBtn->setVisible(show_info_btn); } void showLastInteractionTime(bool show); - void setContextMenu(ContextMenu* menu) { mContextMenu = menu; } - /** * This method was added to fix EXT-2364 (Items in group/ad-hoc IM participant list (avatar names) should be reshaped when adding/removing the "(Moderator)" label) * But this is a *HACK. The real reason of it was in incorrect logic while hiding profile/info/speaker buttons @@ -106,6 +114,8 @@ protected: */ LLOutputMonitorCtrl* mSpeakingIndicator; + LLAvatarIconCtrl* mAvatarIcon; + private: typedef enum e_online_status { @@ -119,14 +129,18 @@ private: std::string formatSeconds(U32 secs); - LLAvatarIconCtrl* mAvatarIcon; + typedef std::map<EItemState, LLStyle::Params> item_style_map_t; + static item_style_map_t& getItemStylesParams(); + + typedef std::map<EItemState, LLColor4> icon_color_map_t; + static icon_color_map_t& getItemIconColorMap(); + LLTextBox* mAvatarName; LLTextBox* mLastInteractionTime; LLStyle::Params mAvatarNameStyle; LLButton* mInfoBtn; LLButton* mProfileBtn; - ContextMenu* mContextMenu; LLUUID mAvatarId; std::string mHighlihtSubstring; // substring to highlight @@ -135,10 +149,12 @@ private: //Speaker indicator and avatar name coords are translated accordingly bool mShowInfoBtn; bool mShowProfileBtn; - S32 mIconWidth; // icon width + padding - S32 mInfoBtnWidth; //info btn width + padding - S32 mProfileBtnWidth; //profile btn width + padding - S32 mSpeakingIndicatorWidth; //speaking indicator width + padding + + static bool sStaticInitialized; // this variable is introduced to improve code readability + static S32 sIconWidth; // icon width + padding + static S32 sInfoBtnWidth; //info btn width + padding + static S32 sProfileBtnWidth; //profile btn width + padding + static S32 sSpeakingIndicatorWidth; //speaking indicator width + padding }; #endif //LL_LLAVATARLISTITEM_H diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index ab657e0e99..976b312509 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -81,9 +81,6 @@ LLBottomTray::LLBottomTray(const LLSD&) LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraPresets, _2)); - //managing chiclets for voice calls - LLIMModel::getInstance()->addNewMsgCallback(boost::bind(&LLBottomTray::onNewIM, this, _1)); - //this is to fix a crash that occurs because LLBottomTray is a singleton //and thus is deleted at the end of the viewers lifetime, but to be cleanly //destroyed LLBottomTray requires some subsystems that are long gone @@ -151,10 +148,13 @@ void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& nam { if (!getChicletPanel()) return; - if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return; + LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); + if (!session) return; - // For im sessions started as voice call chiclet gets created on the first incoming message - if (gIMMgr->isVoiceCall(session_id)) return; + // no need to spawn chiclets for participants in P2P calls called through Avaline + if (session->isP2P() && session->isOtherParticipantAvaline()) return; + + if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return; LLIMChiclet* chiclet = createIMChiclet(session_id); if(chiclet) @@ -197,27 +197,6 @@ void LLBottomTray::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& } } -void LLBottomTray::onNewIM(const LLSD& data) -{ - LLUUID from_id = data["from_id"]; - if (from_id.isNull() || gAgentID == from_id) return; - - LLUUID session_id = data["session_id"]; - if (session_id.isNull()) return; - - if (!gIMMgr->isVoiceCall(session_id)) return; - - if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return; - - //first real message, time to create chiclet - LLIMChiclet* chiclet = createIMChiclet(session_id); - if(chiclet) - { - chiclet->setIMSessionName(LLIMModel::getInstance()->getName(session_id)); - chiclet->setOtherParticipantId(LLIMModel::getInstance()->getOtherParticipantID(session_id)); - } -} - S32 LLBottomTray::getTotalUnreadIMCount() { return getChicletPanel()->getTotalUnreadIMCount(); diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 5cd3f15746..9be0e5810f 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -75,8 +75,6 @@ public: virtual void sessionRemoved(const LLUUID& session_id); void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); - void onNewIM(const LLSD& data); - S32 getTotalUnreadIMCount(); virtual void reshape(S32 width, S32 height, BOOL called_from_parent); diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 20739d2401..a402f59fa1 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -40,6 +40,7 @@ #include "llagent.h" #include "llagentdata.h" // for gAgentID +#include "llavatariconctrl.h" #include "llavatarlist.h" #include "llbottomtray.h" #include "llimfloater.h" @@ -47,7 +48,10 @@ #include "llparticipantlist.h" #include "llspeakers.h" #include "lltransientfloatermgr.h" +#include "llviewerwindow.h" +#include "llvoicechannel.h" +static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids); class LLNonAvatarCaller : public LLAvatarListItem { @@ -66,6 +70,8 @@ public: showLastInteractionTime(false); setShowProfileBtn(false); setShowInfoBtn(false); + mAvatarIcon->setValue("Avaline_Icon"); + mAvatarIcon->setToolTip(std::string("")); } return rv; } @@ -79,17 +85,40 @@ static void* create_non_avatar_caller(void*) return new LLNonAvatarCaller; } +LLCallFloater::LLAvatarListItemRemoveTimer::LLAvatarListItemRemoveTimer(callback_t remove_cb, F32 period, const LLUUID& speaker_id) +: LLEventTimer(period) +, mRemoveCallback(remove_cb) +, mSpeakerId(speaker_id) +{ +} + +BOOL LLCallFloater::LLAvatarListItemRemoveTimer::tick() +{ + if (mRemoveCallback) + { + mRemoveCallback(mSpeakerId); + } + return TRUE; +} + +LLVoiceChannel* LLCallFloater::sCurrentVoiceCanel = NULL; + LLCallFloater::LLCallFloater(const LLSD& key) -: LLDockableFloater(NULL, false, key) +: LLTransientDockableFloater(NULL, false, key) , mSpeakerManager(NULL) -, mPaticipants(NULL) +, mParticipants(NULL) , mAvatarList(NULL) , mNonAvatarCaller(NULL) , mVoiceType(VC_LOCAL_CHAT) , mAgentPanel(NULL) , mSpeakingIndicator(NULL) , mIsModeratorMutedVoice(false) +, mInitParticipantsVoiceState(false) +, mVoiceLeftRemoveDelay(10) { + static LLUICachedControl<S32> voice_left_remove_delay ("VoiceParticipantLeftRemoveDelay", 10); + mVoiceLeftRemoveDelay = voice_left_remove_delay; + mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL); LLVoiceClient::getInstance()->addObserver(this); LLTransientFloaterMgr::getInstance()->addControlView(this); @@ -97,8 +126,13 @@ LLCallFloater::LLCallFloater(const LLSD& key) LLCallFloater::~LLCallFloater() { - delete mPaticipants; - mPaticipants = NULL; + resetVoiceRemoveTimers(); + + delete mParticipants; + mParticipants = NULL; + + mAvatarListRefreshConnection.disconnect(); + mVoiceChannelStateChangeConnection.disconnect(); // Don't use LLVoiceClient::getInstance() here // singleton MAY have already been destroyed. @@ -112,13 +146,16 @@ LLCallFloater::~LLCallFloater() // virtual BOOL LLCallFloater::postBuild() { - LLDockableFloater::postBuild(); + LLTransientDockableFloater::postBuild(); mAvatarList = getChild<LLAvatarList>("speakers_list"); + mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLCallFloater::onAvatarListRefreshed, this)); + childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this)); mNonAvatarCaller = getChild<LLNonAvatarCaller>("non_avatar_caller"); + mNonAvatarCaller->setVisible(FALSE); - LLView *anchor_panel = LLBottomTray::getInstance()->getChild<LLView>("speak_panel"); + LLView *anchor_panel = LLBottomTray::getInstance()->getChild<LLView>("speak_flyout_btn"); setDockControl(new LLDockControl( anchor_panel, this, @@ -126,8 +163,8 @@ BOOL LLCallFloater::postBuild() initAgentData(); - // update list for current session - updateSession(); + + connectToChannel(LLVoiceChannel::getCurrentVoiceChannel()); return TRUE; } @@ -144,7 +181,11 @@ void LLCallFloater::draw() // 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(); + + // NOTE: it looks like calling onChange() here is not necessary, + // but sometime it is not called properly from the observable object. + // Seems this is a problem somewhere in Voice Client (LLVoiceClient::participantAddedEvent) +// onChange(); bool is_moderator_muted = gVoiceClient->getIsModeratorMuted(gAgentID); @@ -153,17 +194,38 @@ void LLCallFloater::draw() setModeratorMutedVoice(is_moderator_muted); } - LLDockableFloater::draw(); + // Need to resort the participant list if it's in sort by recent speaker order. + if (mParticipants) + mParticipants->updateRecentSpeakersOrder(); + + LLTransientDockableFloater::draw(); } // virtual void LLCallFloater::onChange() { - if (NULL == mPaticipants) return; + if (NULL == mParticipants) return; + + updateParticipantsVoiceState(); - mPaticipants->refreshVoiceState(); + // Add newly joined participants. + std::vector<LLUUID> speakers_uuids; + get_voice_participants_uuids(speakers_uuids); + for (std::vector<LLUUID>::const_iterator it = speakers_uuids.begin(); it != speakers_uuids.end(); it++) + { + mParticipants->addAvatarIDExceptAgent(*it); + } } +S32 LLCallFloater::notifyParent(const LLSD& info) +{ + if("size_changes" == info["action"]) + { + reshapeToFitContent(); + return 1; + } + return LLDockableFloater::notifyParent(info); +} ////////////////////////////////////////////////////////////////////////// /// PRIVATE SECTION @@ -242,8 +304,8 @@ void LLCallFloater::updateSession() bool is_local_chat = mVoiceType == VC_LOCAL_CHAT; childSetVisible("leave_call_btn", !is_local_chat); - refreshPartisipantList(); - updateModeratorState(); + refreshParticipantList(); + updateAgentModeratorState(); //show floater for voice calls if (!is_local_chat) @@ -257,12 +319,8 @@ void LLCallFloater::updateSession() } } -void LLCallFloater::refreshPartisipantList() +void LLCallFloater::refreshParticipantList() { - delete mPaticipants; - mPaticipants = NULL; - mAvatarList->clear(); - bool non_avatar_caller = false; if (VC_PEER_TO_PEER == mVoiceType) { @@ -280,31 +338,46 @@ void LLCallFloater::refreshPartisipantList() if (!non_avatar_caller) { - mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList); + mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT); + mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1)); if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager) { mAvatarList->setNoItemsCommentText(getString("no_one_near")); } - mPaticipants->refreshVoiceState(); + + // we have to made delayed initialization of voice state of participant list. + // it will be performed after first LLAvatarList refreshing in the onAvatarListRefreshed(). + mInitParticipantsVoiceState = true; } } -void LLCallFloater::sOnCurrentChannelChanged(const LLUUID& /*session_id*/) +void LLCallFloater::onAvatarListRefreshed() { - // 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()) + if (mInitParticipantsVoiceState) { - return; + initParticipantsVoiceState(); + mInitParticipantsVoiceState = false; } + else + { + updateParticipantsVoiceState(); + } +} + +// static +void LLCallFloater::sOnCurrentChannelChanged(const LLUUID& /*session_id*/) +{ + LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel(); + + // *NOTE: if signal was sent for voice channel with LLVoiceChannel::STATE_NO_CHANNEL_INFO + // it sill be sent for the same channel again (when state is changed). + // So, lets ignore this call. + if (channel == sCurrentVoiceCanel) return; + LLCallFloater* call_floater = LLFloaterReg::getTypedInstance<LLCallFloater>("voice_controls"); - // Forget speaker manager from the previous session to avoid using it after session was destroyed. - call_floater->mSpeakerManager = NULL; - call_floater->updateSession(); + call_floater->connectToChannel(channel); } void LLCallFloater::updateTitle() @@ -366,7 +439,7 @@ void LLCallFloater::setModeratorMutedVoice(bool moderator_muted) mSpeakingIndicator->setIsMuted(moderator_muted); } -void LLCallFloater::updateModeratorState() +void LLCallFloater::updateAgentModeratorState() { std::string name; gCacheName->getFullName(gAgentID, name); @@ -388,4 +461,395 @@ void LLCallFloater::updateModeratorState() } mAgentPanel->childSetValue("user_text", name); } + +static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids) +{ + // Get a list of participants from VoiceClient + LLVoiceClient::participantMap *voice_map = gVoiceClient->getParticipantList(); + if (voice_map) + { + for (LLVoiceClient::participantMap::const_iterator iter = voice_map->begin(); + iter != voice_map->end(); ++iter) + { + LLUUID id = (*iter).second->mAvatarID; + speakers_uuids.push_back(id); + } + } +} + +void LLCallFloater::initParticipantsVoiceState() +{ + // Set initial status for each participant in the list. + std::vector<LLPanel*> items; + mAvatarList->getItems(items); + std::vector<LLPanel*>::const_iterator + it = items.begin(), + it_end = items.end(); + + + std::vector<LLUUID> speakers_uuids; + get_voice_participants_uuids(speakers_uuids); + + for(; it != it_end; ++it) + { + LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it); + + if (!item) continue; + + LLUUID speaker_id = item->getAvatarId(); + + std::vector<LLUUID>::const_iterator speaker_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), speaker_id); + + // If an avatarID assigned to a panel is found in a speakers list + // obtained from VoiceClient we assign the JOINED status to the owner + // of this avatarID. + if (speaker_iter != speakers_uuids.end()) + { + setState(item, STATE_JOINED); + } + else + { + LLPointer<LLSpeaker> speakerp = mSpeakerManager->findSpeaker(speaker_id); + // If someone has already left the call before, we create his + // avatar row panel with HAS_LEFT status and remove it after + // the timeout, otherwise we create a panel with INVITED status + if (speakerp.notNull() && speakerp.get()->mHasLeftCurrentCall) + { + setState(item, STATE_LEFT); + } + else + { + setState(item, STATE_INVITED); + } + } + } +} + +void LLCallFloater::updateParticipantsVoiceState() +{ + std::vector<LLUUID> speakers_list; + + // Get a list of participants from VoiceClient + std::vector<LLUUID> speakers_uuids; + get_voice_participants_uuids(speakers_uuids); + + // Updating the status for each participant already in list. + std::vector<LLPanel*> items; + mAvatarList->getItems(items); + std::vector<LLPanel*>::const_iterator + it = items.begin(), + it_end = items.end(); + + for(; it != it_end; ++it) + { + LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it); + if (!item) continue; + + const LLUUID participant_id = item->getAvatarId(); + bool found = false; + + std::vector<LLUUID>::iterator speakers_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), participant_id); + + lldebugs << "processing speaker: " << item->getAvatarName() << ", " << item->getAvatarId() << llendl; + + // If an avatarID assigned to a panel is found in a speakers list + // obtained from VoiceClient we assign the JOINED status to the owner + // of this avatarID. + if (speakers_iter != speakers_uuids.end()) + { + setState(item, STATE_JOINED); + + LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(participant_id); + if (speaker.isNull()) + continue; + speaker->mHasLeftCurrentCall = FALSE; + + speakers_uuids.erase(speakers_iter); + found = true; + } + + if (!found) + { + // If an avatarID is not found in a speakers list from VoiceClient and + // a panel with this ID has a JOINED status this means that this person + // HAS LEFT the call. + if ((getState(participant_id) == STATE_JOINED)) + { + setState(item, STATE_LEFT); + + LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId()); + if (speaker.isNull()) + { + continue; + } + + speaker->mHasLeftCurrentCall = TRUE; + } + // If an avatarID is not found in a speakers list from VoiceClient and + // a panel with this ID has a LEFT status this means that this person + // HAS ENTERED session but it is not in voice chat yet. So, set INVITED status + else if ((getState(participant_id) != STATE_LEFT)) + { + setState(item, STATE_INVITED); + } + else + { + llwarns << "Unsupported (" << getState(participant_id) << ") state: " << item->getAvatarName() << llendl; + } + } + } +} + +void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state) +{ + // *HACK: mantipov: sometimes such situation is possible while switching to voice channel: +/* + - voice channel is switched to the one user is joining + - participant list is initialized with voice states: agent is in voice + - than such log messages were found (with agent UUID) + - LLVivoxProtocolParser::process_impl: parsing: <Response requestId="22" action="Session.MediaDisconnect.1"><ReturnCode>0</ReturnCode><Results><StatusCode>0</StatusCode><StatusString /></Results><InputXml><Request requestId="22" action="Session.MediaDisconnect.1"><SessionGroupHandle>9</SessionGroupHandle><SessionHandle>12</SessionHandle><Media>Audio</Media></Request></InputXml></Response> + - LLVoiceClient::sessionState::removeParticipant: participant "sip:x2pwNkMbpR_mK4rtB_awASA==@bhr.vivox.com" (da9c0d90-c6e9-47f9-8ae2-bb41fdac0048) removed. + - and than while updating participants voice states agent is marked as HAS LEFT + - next updating of LLVoiceClient state makes agent JOINED + So, lets skip HAS LEFT state for agent's avatar +*/ + if (STATE_LEFT == state && item->getAvatarId() == gAgentID) return; + + setState(item->getAvatarId(), state); + + switch (state) + { + case STATE_INVITED: + item->setState(LLAvatarListItem::IS_VOICE_INVITED); + break; + case STATE_JOINED: + removeVoiceRemoveTimer(item->getAvatarId()); + item->setState(LLAvatarListItem::IS_VOICE_JOINED); + break; + case STATE_LEFT: + { + setVoiceRemoveTimer(item->getAvatarId()); + item->setState(LLAvatarListItem::IS_VOICE_LEFT); + } + break; + default: + llwarns << "Unrecognized avatar panel state (" << state << ")" << llendl; + break; + } +} + +void LLCallFloater::setVoiceRemoveTimer(const LLUUID& voice_speaker_id) +{ + + // If there is already a started timer for the current panel don't do anything. + bool no_timer_for_current_panel = true; + if (mVoiceLeftTimersMap.size() > 0) + { + timers_map::iterator found_it = mVoiceLeftTimersMap.find(voice_speaker_id); + if (found_it != mVoiceLeftTimersMap.end()) + { + no_timer_for_current_panel = false; + } + } + + if (no_timer_for_current_panel) + { + // Starting a timer to remove an avatar row panel after timeout + mVoiceLeftTimersMap.insert(timer_pair(voice_speaker_id, + new LLAvatarListItemRemoveTimer(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), mVoiceLeftRemoveDelay, voice_speaker_id))); + } +} + +void LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id) +{ + if (mVoiceLeftTimersMap.size() > 0) + { + mVoiceLeftTimersMap.erase(mVoiceLeftTimersMap.find(voice_speaker_id)); + } + + LLAvatarList::uuid_vector_t& speaker_uuids = mAvatarList->getIDs(); + LLAvatarList::uuid_vector_t::iterator pos = std::find(speaker_uuids.begin(), speaker_uuids.end(), voice_speaker_id); + if(pos != speaker_uuids.end()) + { + speaker_uuids.erase(pos); + mAvatarList->setDirty(); + } +} + + +void LLCallFloater::resetVoiceRemoveTimers() +{ + if (mVoiceLeftTimersMap.size() > 0) + { + for (timers_map::iterator iter = mVoiceLeftTimersMap.begin(); + iter != mVoiceLeftTimersMap.end(); ++iter) + { + delete iter->second; + } + } + mVoiceLeftTimersMap.clear(); +} + +void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id) +{ + // Remove the timer if it has been already started + if (mVoiceLeftTimersMap.size() > 0) + { + timers_map::iterator found_it = mVoiceLeftTimersMap.find(voice_speaker_id); + if (found_it != mVoiceLeftTimersMap.end()) + { + delete found_it->second; + mVoiceLeftTimersMap.erase(found_it); + } + } +} + +bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id) +{ + if (mVoiceType != VC_LOCAL_CHAT) + return true; + + // A nearby chat speaker is considered valid it it's known to LLVoiceClient (i.e. has enabled voice). + std::vector<LLUUID> speakers; + get_voice_participants_uuids(speakers); + return std::find(speakers.begin(), speakers.end(), speaker_id) != speakers.end(); +} + +void LLCallFloater::connectToChannel(LLVoiceChannel* channel) +{ + mVoiceChannelStateChangeConnection.disconnect(); + + sCurrentVoiceCanel = channel; + + mVoiceChannelStateChangeConnection = sCurrentVoiceCanel->setStateChangedCallback(boost::bind(&LLCallFloater::onVoiceChannelStateChanged, this, _1, _2)); + + updateState(channel->getState()); +} + +void LLCallFloater::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) +{ + updateState(new_state); +} + +void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state) +{ + LL_DEBUGS("Voice") << "Updating state: " << new_state << ", session name: " << sCurrentVoiceCanel->getSessionName() << LL_ENDL; + if (LLVoiceChannel::STATE_CONNECTED == new_state) + { + updateSession(); + } + else + { + reset(); + } +} + +void LLCallFloater::reset() +{ + // lets forget states from the previous session + // for timers... + resetVoiceRemoveTimers(); + + // ...and for speaker state + mSpeakerStateMap.clear(); + + delete mParticipants; + mParticipants = NULL; + mAvatarList->clear(); + + // update floater to show Loading while waiting for data. + mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); + mAvatarList->setVisible(TRUE); + mNonAvatarCaller->setVisible(FALSE); + + mSpeakerManager = NULL; +} + +void reshape_floater(LLCallFloater* floater, S32 delta_height) +{ + // Try to update floater top side if it is docked(to bottom bar). + // Try to update floater bottom side or top side if it is un-docked. + // If world rect is too small, floater will not be reshaped at all. + + LLRect floater_rect = floater->getRect(); + LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); + + // floater is docked to bottom bar + if(floater->isDocked()) + { + // can update floater top side + if(floater_rect.mTop + delta_height < world_rect.mTop) + { + floater_rect.set(floater_rect.mLeft, floater_rect.mTop + delta_height, + floater_rect.mRight, floater_rect.mBottom); + } + } + // floater is un-docked + else + { + // can update floater bottom side + if( floater_rect.mBottom - delta_height >= world_rect.mBottom ) + { + floater_rect.set(floater_rect.mLeft, floater_rect.mTop, + floater_rect.mRight, floater_rect.mBottom - delta_height); + } + // could not update floater bottom side, check if we can update floater top side + else if( floater_rect.mTop + delta_height < world_rect.mTop ) + { + floater_rect.set(floater_rect.mLeft, floater_rect.mTop + delta_height, + floater_rect.mRight, floater_rect.mBottom); + } + } + + floater->reshape(floater_rect.getWidth(), floater_rect.getHeight()); + floater->setRect(floater_rect); +} + +void LLCallFloater::reshapeToFitContent() +{ + const S32 ITEM_HEIGHT = getParticipantItemHeight(); + static const S32 MAX_VISIBLE_ITEMS = getMaxVisibleItems(); + + static S32 items_pad = mAvatarList->getItemsPad(); + S32 list_height = mAvatarList->getRect().getHeight(); + S32 items_height = mAvatarList->getItemsRect().getHeight(); + if(items_height <= 0) + { + // make "no one near" text visible + items_height = ITEM_HEIGHT + items_pad; + } + S32 max_list_height = MAX_VISIBLE_ITEMS * ITEM_HEIGHT + items_pad * (MAX_VISIBLE_ITEMS - 1); + max_list_height += 2* mAvatarList->getBorderWidth(); + + S32 delta = items_height - list_height; + // too many items, don't reshape floater anymore, let scroll bar appear. + if(items_height > max_list_height) + { + delta = max_list_height - list_height; + } + + reshape_floater(this, delta); +} + +S32 LLCallFloater::getParticipantItemHeight() +{ + std::vector<LLPanel*> items; + mAvatarList->getItems(items); + if(items.size() > 0) + { + return items[0]->getRect().getHeight(); + } + else + { + return getChild<LLPanel>("non_avatar_caller")->getRect().getHeight(); + } +} + +S32 LLCallFloater::getMaxVisibleItems() +{ + S32 value = 5; // default value, in case convertToS32() fails. + LLStringUtil::convertToS32(getString("max_visible_items"), value); + return value; +} + //EOF diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index f9c9149085..8aba93fc43 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -34,10 +34,12 @@ #ifndef LL_LLCALLFLOATER_H #define LL_LLCALLFLOATER_H -#include "lldockablefloater.h" +#include "lltransientdockablefloater.h" +#include "llvoicechannel.h" #include "llvoiceclient.h" class LLAvatarList; +class LLAvatarListItem; class LLNonAvatarCaller; class LLOutputMonitorCtrl; class LLParticipantList; @@ -53,9 +55,12 @@ 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, LLVoiceClientParticipantObserver +class LLCallFloater : public LLTransientDockableFloater, LLVoiceClientParticipantObserver { public: + + LOG_CLASS(LLCallFloater); + LLCallFloater(const LLSD& key); ~LLCallFloater(); @@ -70,6 +75,11 @@ public: */ /*virtual*/ void onChange(); + /** + * Will reshape floater when participant list size changes + */ + /*virtual*/ S32 notifyParent(const LLSD& info); + static void sOnCurrentChannelChanged(const LLUUID& session_id); private: @@ -81,6 +91,16 @@ private: VC_PEER_TO_PEER }EVoiceControls; + typedef enum e_speaker_state + { + STATE_UNKNOWN, + STATE_INVITED, + STATE_JOINED, + STATE_LEFT, + } ESpeakerState; + + typedef std::map<LLUUID, ESpeakerState> speaker_state_map_t; + void leaveCall(); /** @@ -94,24 +114,187 @@ private: /** * Refreshes participant list according to current Voice Channel */ - void refreshPartisipantList(); + void refreshParticipantList(); + /** + * Handles event on avatar list is refreshed after it was marked dirty. + * + * It sets initial participants voice states (once after the first refreshing) + * and updates voice states each time anybody is joined/left voice chat in session. + */ + void onAvatarListRefreshed(); void updateTitle(); void initAgentData(); void setModeratorMutedVoice(bool moderator_muted); - void updateModeratorState(); + void updateAgentModeratorState(); + + /** + * Sets initial participants voice states in avatar list (Invited, Joined, Has Left). + * + * @see refreshParticipantList() + * @see onAvatarListRefreshed() + * @see mInitParticipantsVoiceState + */ + void initParticipantsVoiceState(); + + /** + * Updates participants voice states in avatar list (Invited, Joined, Has Left). + * + * @see onAvatarListRefreshed() + * @see onChanged() + */ + void updateParticipantsVoiceState(); + + void setState(LLAvatarListItem* item, ESpeakerState state); + void setState(const LLUUID& speaker_id, ESpeakerState state) + { + lldebugs << "Storing state: " << speaker_id << ", " << state << llendl; + mSpeakerStateMap[speaker_id] = state; + } + + ESpeakerState getState(const LLUUID& speaker_id) + { + lldebugs << "Getting state: " << speaker_id << ", " << mSpeakerStateMap[speaker_id] << llendl; + + return mSpeakerStateMap[speaker_id]; + } + + /** + * Instantiates new LLAvatarListItemRemoveTimer and adds it into the map if it is not already created. + * + * @param voice_speaker_id LLUUID of Avatar List item to be removed from the list when timer expires. + */ + void setVoiceRemoveTimer(const LLUUID& voice_speaker_id); + + /** + * Removes specified by UUID Avatar List item. + * + * @param voice_speaker_id LLUUID of Avatar List item to be removed from the list. + */ + void removeVoiceLeftParticipant(const LLUUID& voice_speaker_id); + + /** + * Deletes all timers from the list to prevent started timers from ticking after destruction + * and after switching on another voice channel. + */ + void resetVoiceRemoveTimers(); + + /** + * Removes specified by UUID timer from the map. + * + * @param voice_speaker_id LLUUID of Avatar List item whose timer should be removed from the map. + */ + void removeVoiceRemoveTimer(const LLUUID& voice_speaker_id); + + /** + * Called by LLParticipantList before adding a speaker to the participant list. + * + * If false is returned, the speaker will not be added to the list. + * + * @param speaker_id Speaker to validate. + * @return true if this is a valid speaker, false otherwise. + */ + bool validateSpeaker(const LLUUID& speaker_id); + + /** + * Connects to passed channel to be updated according to channel's voice states. + */ + void connectToChannel(LLVoiceChannel* channel); + + /** + * Callback to process changing of voice channel's states. + */ + void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); + + /** + * Updates floater according to passed channel's voice state. + */ + void updateState(const LLVoiceChannel::EState& new_state); + + /** + * Resets floater to be ready to show voice participants. + * + * Clears all data from the latest voice session. + */ + void reset(); + + /** + * Reshapes floater to fit participant list height + */ + void reshapeToFitContent(); + + /** + * Returns height of participant list item + */ + S32 getParticipantItemHeight(); + + /** + * Returns predefined max visible participants. + */ + S32 getMaxVisibleItems(); private: + speaker_state_map_t mSpeakerStateMap; LLSpeakerMgr* mSpeakerManager; - LLParticipantList* mPaticipants; + LLParticipantList* mParticipants; LLAvatarList* mAvatarList; LLNonAvatarCaller* mNonAvatarCaller; EVoiceControls mVoiceType; LLPanel* mAgentPanel; LLOutputMonitorCtrl* mSpeakingIndicator; bool mIsModeratorMutedVoice; + + /** + * Flag indicated that participants voice states should be initialized. + * + * It is used due to Avatar List has delayed refreshing after it content is changed. + * Real initializing is performed when Avatar List is first time refreshed. + * + * @see onAvatarListRefreshed() + * @see initParticipantsVoiceState() + */ + bool mInitParticipantsVoiceState; + + boost::signals2::connection mAvatarListRefreshConnection; + + /** + * class LLAvatarListItemRemoveTimer + * + * Implements a timer that removes avatar list item of a participant + * who has left the call. + */ + class LLAvatarListItemRemoveTimer : public LLEventTimer + { + public: + typedef boost::function<void(const LLUUID&)> callback_t; + + LLAvatarListItemRemoveTimer(callback_t remove_cb, F32 period, const LLUUID& speaker_id); + virtual ~LLAvatarListItemRemoveTimer() {}; + + virtual BOOL tick(); + + private: + callback_t mRemoveCallback; + LLUUID mSpeakerId; + }; + + typedef std::pair<LLUUID, LLAvatarListItemRemoveTimer*> timer_pair; + typedef std::map<LLUUID, LLAvatarListItemRemoveTimer*> timers_map; + + timers_map mVoiceLeftTimersMap; + S32 mVoiceLeftRemoveDelay; + + /** + * Stores reference to current voice channel. + * + * Is used to ignore voice channel changed callback for the same channel. + * + * @see sOnCurrentChannelChanged() + */ + static LLVoiceChannel* sCurrentVoiceCanel; + boost::signals2::connection mVoiceChannelStateChangeConnection; }; diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 82413878ad..d988770f90 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -62,7 +62,6 @@ #include "llviewerobjectlist.h" #include "llviewerwindow.h" #include "llvoavatar.h" -#include "llimview.h" ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index cbb566b3a7..769387c26c 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -36,7 +36,6 @@ #include "llappviewer.h" #include "llviewercontrol.h" -#include "llimview.h" #include "llviewerwindow.h" #include "llrootview.h" #include "llsyswellwindow.h" diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 7a83299dac..21cadda6e3 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -31,12 +31,14 @@ */ #include "llviewerprecompiledheaders.h" + +#include "llinstantmessage.h" + #include "llchathistory.h" #include "llpanel.h" #include "lluictrlfactory.h" #include "llscrollcontainer.h" #include "llavatariconctrl.h" -#include "llimview.h" #include "llcallingcard.h" //for LLAvatarTracker #include "llagentdata.h" #include "llavataractions.h" @@ -44,6 +46,8 @@ #include "llfloaterreg.h" #include "llmutelist.h" #include "llstylemap.h" +#include "lllayoutstack.h" +#include "llagent.h" #include "llsidetray.h"//for blocked objects panel @@ -346,18 +350,23 @@ protected: LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) -: LLTextEditor(p), -mMessageHeaderFilename(p.message_header), -mMessageSeparatorFilename(p.message_separator), -mLeftTextPad(p.left_text_pad), -mRightTextPad(p.right_text_pad), -mLeftWidgetPad(p.left_widget_pad), -mRightWidgetPad(p.right_widget_pad), -mTopSeparatorPad(p.top_separator_pad), -mBottomSeparatorPad(p.bottom_separator_pad), -mTopHeaderPad(p.top_header_pad), -mBottomHeaderPad(p.bottom_header_pad) +: LLUICtrl(p), + mMessageHeaderFilename(p.message_header), + mMessageSeparatorFilename(p.message_separator), + mLeftTextPad(p.left_text_pad), + mRightTextPad(p.right_text_pad), + mLeftWidgetPad(p.left_widget_pad), + mRightWidgetPad(p.right_widget_pad), + mTopSeparatorPad(p.top_separator_pad), + mBottomSeparatorPad(p.bottom_separator_pad), + mTopHeaderPad(p.top_header_pad), + mBottomHeaderPad(p.bottom_header_pad) { + LLTextEditor::Params editor_params(p); + editor_params.rect = getLocalRect(); + editor_params.follows.flags = FOLLOWS_ALL; + editor_params.enabled = false; // read only + mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this); } LLChatHistory::~LLChatHistory() @@ -365,6 +374,49 @@ LLChatHistory::~LLChatHistory() this->clear(); } +void LLChatHistory::initFromParams(const LLChatHistory::Params& p) +{ + static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + + LLRect stack_rect = getLocalRect(); + stack_rect.mRight -= scrollbar_size; + LLLayoutStack::Params layout_p; + layout_p.rect = stack_rect; + layout_p.follows.flags = FOLLOWS_ALL; + layout_p.orientation = "vertical"; + layout_p.mouse_opaque = false; + + LLLayoutStack* stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p, this); + + const S32 NEW_TEXT_NOTICE_HEIGHT = 20; + + LLPanel::Params panel_p; + panel_p.name = "spacer"; + panel_p.background_visible = false; + panel_p.has_border = false; + panel_p.mouse_opaque = false; + stackp->addPanel(LLUICtrlFactory::create<LLPanel>(panel_p), 0, 30, true, false, LLLayoutStack::ANIMATE); + + panel_p.name = "new_text_notice_holder"; + LLRect new_text_notice_rect = getLocalRect(); + new_text_notice_rect.mTop = new_text_notice_rect.mBottom + NEW_TEXT_NOTICE_HEIGHT; + panel_p.rect = new_text_notice_rect; + panel_p.background_opaque = true; + panel_p.background_visible = true; + panel_p.visible = false; + mMoreChatPanel = LLUICtrlFactory::create<LLPanel>(panel_p); + + LLTextBox::Params text_p(p.more_chat_text); + text_p.rect = mMoreChatPanel->getLocalRect(); + text_p.follows.flags = FOLLOWS_ALL; + text_p.name = "more_chat_text"; + mMoreChatText = LLUICtrlFactory::create<LLTextBox>(text_p, mMoreChatPanel); + mMoreChatText->setClickedCallback(boost::bind(&LLChatHistory::onClickMoreText, this)); + + stackp->addPanel(mMoreChatPanel, 0, 0, false, false, LLLayoutStack::ANIMATE); +} + + /*void LLChatHistory::updateTextRect() { static LLUICachedControl<S32> texteditor_border ("UITextEditorBorder", 0); @@ -393,15 +445,49 @@ LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style return header; } +void LLChatHistory::onClickMoreText() +{ + mEditor->endOfDoc(); +} + void LLChatHistory::clear() { mLastFromName.clear(); - LLTextEditor::clear(); + mEditor->clear(); mLastFromID = LLUUID::null; } void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_chat_history, const LLStyle::Params& input_append_params) { + if (!mEditor->scrolledToEnd() && chat.mFromID != gAgent.getID() && !chat.mFromName.empty()) + { + mUnreadChatSources.insert(chat.mFromName); + mMoreChatPanel->setVisible(TRUE); + std::string chatters; + for (unread_chat_source_t::iterator it = mUnreadChatSources.begin(); + it != mUnreadChatSources.end();) + { + chatters += *it; + if (++it != mUnreadChatSources.end()) + { + chatters += ","; + } + } + LLStringUtil::format_map_t args; + args["SOURCES"] = chatters; + + if (mUnreadChatSources.size() == 1) + { + mMoreChatText->setValue(LLTrans::getString("unread_chat_single", args)); + } + else + { + mMoreChatText->setValue(LLTrans::getString("unread_chat_multiple", args)); + } + S32 height = mMoreChatText->getTextPixelHeight() + 5; + mMoreChatPanel->reshape(mMoreChatPanel->getRect().getWidth(), height); + } + LLColor4 txt_color = LLUIColorTable::instance().getColor("White"); LLViewerChat::getChatColor(chat,txt_color); LLFontGL* fontp = LLViewerChat::getChatFont(); @@ -416,7 +502,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ if (use_plain_text_chat_history) { - appendText("[" + chat.mTimeStr + "] ", getText().size() != 0, style_params); + mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, style_params); if (utf8str_trim(chat.mFromName).size() != 0) { @@ -426,11 +512,11 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ LLStyle::Params link_params(style_params); link_params.fillFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); // Convert the name to a hotlink and add to message. - appendText(chat.mFromName + ": ", false, link_params); + mEditor->appendText(chat.mFromName + ": ", false, link_params); } else { - appendText(chat.mFromName + ": ", false, style_params); + mEditor->appendText(chat.mFromName + ": ", false, style_params); } } } @@ -457,7 +543,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ else { view = getHeader(chat, style_params); - if (getText().size() == 0) + if (mEditor->getText().size() == 0) p.top_pad = 0; else p.top_pad = mTopHeaderPad; @@ -467,9 +553,9 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ p.view = view; //Prepare the rect for the view - LLRect target_rect = getDocumentView()->getRect(); + LLRect target_rect = mEditor->getDocumentView()->getRect(); // squeeze down the widget by subtracting padding off left and right - target_rect.mLeft += mLeftWidgetPad + mHPad; + target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad(); target_rect.mRight -= mRightWidgetPad; view->reshape(target_rect.getWidth(), view->getRect().getHeight()); view->setOrigin(target_rect.mLeft, view->getRect().mBottom); @@ -478,7 +564,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ if (utf8str_trim(chat.mFromName).size() != 0 && chat.mFromName != SYSTEM_FROM) header_text += chat.mFromName + ": "; - appendWidget(p, header_text, false); + mEditor->appendWidget(p, header_text, false); mLastFromName = chat.mFromName; mLastFromID = chat.mFromID; mLastMessageTime = new_message_time; @@ -490,10 +576,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ style_params.font.style = "ITALIC"; if (chat.mFromName.size() > 0) - appendText(chat.mFromName + " ", TRUE, style_params); + mEditor->appendText(chat.mFromName + " ", TRUE, 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); + mEditor->appendText(chat.mText.substr(4) + NEW_LINE, FALSE, style_params); } else { @@ -504,8 +590,19 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ // while copy/paste from text chat. See EXT-3263. message += NEW_LINE; } - appendText(message, FALSE, style_params); + mEditor->appendText(message, FALSE, style_params); + } + mEditor->blockUndo(); +} + +void LLChatHistory::draw() +{ + if (mEditor->scrolledToEnd()) + { + mUnreadChatSources.clear(); + mMoreChatPanel->setVisible(FALSE); } - blockUndo(); + + LLUICtrl::draw(); } diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 8ca7dd1d58..260015e2dc 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -34,10 +34,11 @@ #define LLCHATHISTORY_H_ #include "lltexteditor.h" +#include "lltextbox.h" #include "llviewerchat.h" //Chat log widget allowing addition of a message as a widget -class LLChatHistory : public LLTextEditor +class LLChatHistory : public LLUICtrl { public: struct Params : public LLInitParam::Block<Params, LLTextEditor::Params> @@ -63,6 +64,8 @@ class LLChatHistory : public LLTextEditor //Header bottom padding Optional<S32> bottom_header_pad; + Optional<LLTextBox::Params> more_chat_text; + Params() : message_header("message_header"), message_separator("message_separator"), @@ -73,15 +76,16 @@ class LLChatHistory : public LLTextEditor top_separator_pad("top_separator_pad"), bottom_separator_pad("bottom_separator_pad"), top_header_pad("top_header_pad"), - bottom_header_pad("bottom_header_pad") - { - } + bottom_header_pad("bottom_header_pad"), + more_chat_text("more_chat_text") + {} }; protected: LLChatHistory(const Params&); friend class LLUICtrlFactory; + /*virtual*/ void draw(); /** * Redefinition of LLTextEditor::updateTextRect() to considerate text * left/right padding params. @@ -98,9 +102,13 @@ class LLChatHistory : public LLTextEditor */ LLView* getHeader(const LLChat& chat,const LLStyle::Params& style_params); + void onClickMoreText(); + public: ~LLChatHistory(); + void initFromParams(const Params&); + /** * Appends a widget message. * If last user appended message, concurs with current user, @@ -129,5 +137,11 @@ class LLChatHistory : public LLTextEditor S32 mBottomSeparatorPad; S32 mTopHeaderPad; S32 mBottomHeaderPad; + + LLPanel* mMoreChatPanel; + LLTextBox* mMoreChatText; + LLTextEditor* mEditor; + typedef std::set<std::string> unread_chat_source_t; + unread_chat_source_t mUnreadChatSources; }; #endif /* LLCHATHISTORY_H_ */ diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 21a0381495..dc2e22f899 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -49,7 +49,6 @@ #include "llscriptfloater.h" #include "lltextbox.h" #include "llvoiceclient.h" -#include "llvoicecontrolpanel.h" #include "llgroupmgr.h" #include "llnotificationmanager.h" #include "lltransientfloatermgr.h" @@ -64,17 +63,6 @@ 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); -static const LLRect VOICE_INDICATOR_RECT(50, 25, 70, 0); -static const LLRect COUNTER_RECT(25, 25, 50, 0); -static const S32 OVERLAY_ICON_SHIFT = 2; // used for shifting of an overlay icon for new massages in a chiclet - -// static -const S32 LLChicletPanel::s_scroll_ratio = 10; -const S32 LLChicletNotificationCounterCtrl::MAX_DISPLAYED_COUNT = 99; - - boost::signals2::signal<LLChiclet* (const LLUUID&), LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > > LLIMChiclet::sFindChicletsSignal; @@ -140,7 +128,7 @@ private: LLSysWellChiclet::Params::Params() : button("button") , unread_notifications("unread_notifications") -, max_displayed_count("max_displayed_count", 9) +, max_displayed_count("max_displayed_count", 99) , flash_to_lit_count("flash_to_lit_count", 3) , flash_period("flash_period", 0.5F) { @@ -172,6 +160,9 @@ LLSysWellChiclet::~LLSysWellChiclet() void LLSysWellChiclet::setCounter(S32 counter) { + // do nothing if the same counter is coming. EXT-3678. + if (counter == mCounter) return; + // note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter) std::string s_count; if(counter != 0) @@ -186,9 +177,9 @@ void LLSysWellChiclet::setCounter(S32 counter) mButton->setLabel(s_count); - setNewMessagesState(counter > 0); + setNewMessagesState(counter > mCounter); - // we have to flash to 'Lit' state each time new unread message is comming. + // we have to flash to 'Lit' state each time new unread message is coming. if (counter > mCounter) { mFlashToLitTimer->flash(); @@ -233,6 +224,10 @@ void LLSysWellChiclet::setNewMessagesState(bool new_messages) mIsNewMessagesState = new_messages; } +void LLSysWellChiclet::updateWidget(bool is_window_empty) +{ + mButton->setEnabled(!is_window_empty); +} // virtual BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) { @@ -382,14 +377,21 @@ void LLNotificationChiclet::createMenu() LLViewerMenuHolderGL::child_registry_t::instance()); } +/*virtual*/ +void LLNotificationChiclet::setCounter(S32 counter) +{ + LLSysWellChiclet::setCounter(counter); + updateWidget(getCounter() == 0); + +} ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// LLChiclet::Params::Params() - : show_counter("show_counter") + : show_counter("show_counter", true) + , enable_counter("enable_counter", false) { - show_counter = true; } LLChiclet::LLChiclet(const Params& p) @@ -447,26 +449,12 @@ void LLChiclet::setValue(const LLSD& value) LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p) : LLChiclet(p) , mShowSpeaker(false) +, mDefaultWidth(p.rect().getWidth()) , mNewMessagesIcon(NULL) , mSpeakerCtrl(NULL) , mCounterCtrl(NULL) { - // initialize an overlay icon for new messages - LLIconCtrl::Params icon_params; - icon_params.visible = false; - icon_params.image = LLUI::getUIImage(p.new_messages_icon_name); - mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(icon_params); - addChild(mNewMessagesIcon); - - // adjust size and position of an icon - LLRect chiclet_rect = p.rect; - LLRect overlay_icon_rect = LLRect(chiclet_rect.getWidth()/2, chiclet_rect.getHeight(), chiclet_rect.getWidth(), chiclet_rect.getHeight()/2); - mNewMessagesIcon->setRect(overlay_icon_rect); - - // shift an icon a little bit to the right and up corner of a chiclet - overlay_icon_rect.translate(OVERLAY_ICON_SHIFT, OVERLAY_ICON_SHIFT); - - enableCounterControl(false); + enableCounterControl(p.enable_counter); } void LLIMChiclet::setShowSpeaker(bool show) @@ -476,7 +464,6 @@ void LLIMChiclet::setShowSpeaker(bool show) { mShowSpeaker = show; toggleSpeakerControl(); - onChicletSizeChanged(); } } @@ -501,7 +488,6 @@ void LLIMChiclet::setShowCounter(bool show) { LLChiclet::setShowCounter(show); toggleCounterControl(); - onChicletSizeChanged(); } } @@ -514,32 +500,37 @@ void LLIMChiclet::setRequiredWidth() { bool show_speaker = getShowSpeaker(); bool show_counter = getShowCounter(); - S32 required_width = CHICLET_RECT.getWidth(); + S32 required_width = mDefaultWidth; if (show_counter) { - required_width += COUNTER_RECT.getWidth(); + required_width += mCounterCtrl->getRect().getWidth(); } if (show_speaker) { - required_width += VOICE_INDICATOR_RECT.getWidth(); + required_width += mSpeakerCtrl->getRect().getWidth(); } reshape(required_width, getRect().getHeight()); + + onChicletSizeChanged(); } void LLIMChiclet::toggleSpeakerControl() { if(getShowSpeaker()) { + // move speaker to the right of chiclet icon + LLRect speaker_rc = mSpeakerCtrl->getRect(); + speaker_rc.setLeftTopAndSize(mDefaultWidth, speaker_rc.mTop, speaker_rc.getWidth(), speaker_rc.getHeight()); + mSpeakerCtrl->setRect(speaker_rc); + if(getShowCounter()) { - mSpeakerCtrl->setRect(VOICE_INDICATOR_RECT); - } - else - { - mSpeakerCtrl->setRect(COUNTER_RECT); + // move speaker to the right of counter + mSpeakerCtrl->translate(mCounterCtrl->getRect().getWidth(), 0); } + initSpeakerControl(); } @@ -566,6 +557,7 @@ void LLIMChiclet::setShowNewMessagesIcon(bool show) { mNewMessagesIcon->setVisible(show); } + setRequiredWidth(); } bool LLIMChiclet::getShowNewMessagesIcon() @@ -639,36 +631,9 @@ LLIMP2PChiclet::Params::Params() : avatar_icon("avatar_icon") , unread_notifications("unread_notifications") , speaker("speaker") +, new_message_icon("new_message_icon") , show_speaker("show_speaker") { - // *TODO Vadim: Get rid of hardcoded values. - rect(CHICLET_RECT); - - avatar_icon.name("avatar_icon"); - avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - - // *NOTE dzaporozhan - // Changed icon height from 25 to 24 to fix ticket EXT-794. - // In some cases(after changing UI scale) 25 pixel height icon was - // drawn incorrectly, i'm not sure why. - avatar_icon.rect(CHICLET_ICON_RECT); - avatar_icon.mouse_opaque(false); - - unread_notifications.name("unread"); - unread_notifications.font(LLFontGL::getFontSansSerif()); - unread_notifications.font_halign(LLFontGL::HCENTER); - unread_notifications.v_pad(5); - unread_notifications.text_color(LLColor4::white); - unread_notifications.mouse_opaque(false); - unread_notifications.rect(COUNTER_RECT); - unread_notifications.visible(false); - - speaker.name("speaker"); - speaker.rect(VOICE_INDICATOR_RECT); - speaker.auto_update(true); - speaker.draw_border(false); - - show_speaker = false; } LLIMP2PChiclet::LLIMP2PChiclet(const Params& p) @@ -676,6 +641,10 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p) , mChicletIconCtrl(NULL) , mPopupMenu(NULL) { + LLIconCtrl::Params new_msg_params = p.new_message_icon; + mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); + addChild(mNewMessagesIcon); + LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon; mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params); addChild(mChicletIconCtrl); @@ -693,10 +662,6 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p) sendChildToFront(mNewMessagesIcon); setShowSpeaker(p.show_speaker); - - //since mShowSpeaker initialized with false - //setShowSpeaker(false) will not hide mSpeakerCtrl - mSpeakerCtrl->setVisible(getShowSpeaker()); } void LLIMP2PChiclet::initSpeakerControl() @@ -717,8 +682,11 @@ void LLIMP2PChiclet::updateMenuItems() if(getSessionId().isNull()) return; + LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId()); + bool open_window_exists = open_im_floater && open_im_floater->getVisible(); + mPopupMenu->getChild<LLUICtrl>("Send IM")->setEnabled(!open_window_exists); + bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId()); - mPopupMenu->getChild<LLUICtrl>("Add Friend")->setEnabled(!is_friend); } @@ -789,38 +757,10 @@ LLAdHocChiclet::Params::Params() : avatar_icon("avatar_icon") , unread_notifications("unread_notifications") , speaker("speaker") +, new_message_icon("new_message_icon") , show_speaker("show_speaker") , avatar_icon_color("avatar_icon_color", LLColor4::green) { - // *TODO Vadim: Get rid of hardcoded values. - rect(CHICLET_RECT); - - avatar_icon.name("avatar_icon"); - avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - - // *NOTE dzaporozhan - // Changed icon height from 25 to 24 to fix ticket EXT-794. - // In some cases(after changing UI scale) 25 pixel height icon was - // drawn incorrectly, i'm not sure why. - avatar_icon.rect(CHICLET_ICON_RECT); - avatar_icon.mouse_opaque(false); - - unread_notifications.name("unread"); - unread_notifications.font(LLFontGL::getFontSansSerif()); - unread_notifications.font_halign(LLFontGL::HCENTER); - unread_notifications.v_pad(5); - unread_notifications.text_color(LLColor4::white); - unread_notifications.mouse_opaque(false); - unread_notifications.rect(COUNTER_RECT); - unread_notifications.visible(false); - - - speaker.name("speaker"); - speaker.rect(VOICE_INDICATOR_RECT); - speaker.auto_update(true); - speaker.draw_border(false); - - show_speaker = false; } LLAdHocChiclet::LLAdHocChiclet(const Params& p) @@ -828,6 +768,10 @@ LLAdHocChiclet::LLAdHocChiclet(const Params& p) , mChicletIconCtrl(NULL) , mPopupMenu(NULL) { + LLIconCtrl::Params new_msg_params = p.new_message_icon; + mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); + addChild(mNewMessagesIcon); + LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon; mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params); //Make the avatar modified @@ -940,32 +884,9 @@ LLIMGroupChiclet::Params::Params() : group_icon("group_icon") , unread_notifications("unread_notifications") , speaker("speaker") +, new_message_icon("new_message_icon") , show_speaker("show_speaker") { - rect(CHICLET_RECT); - - group_icon.name("group_icon"); - - // *NOTE dzaporozhan - // Changed icon height from 25 to 24 to fix ticket EXT-794. - // In some cases(after changing UI scale) 25 pixel height icon was - // drawn incorrectly, i'm not sure why. - group_icon.rect(CHICLET_ICON_RECT); - - unread_notifications.name("unread"); - unread_notifications.font(LLFontGL::getFontSansSerif()); - unread_notifications.font_halign(LLFontGL::HCENTER); - unread_notifications.v_pad(5); - unread_notifications.text_color(LLColor4::white); - unread_notifications.rect(COUNTER_RECT); - unread_notifications.visible(false); - - speaker.name("speaker"); - speaker.rect(VOICE_INDICATOR_RECT); - speaker.auto_update(true); - speaker.draw_border(false); - - show_speaker = false; } LLIMGroupChiclet::LLIMGroupChiclet(const Params& p) @@ -974,6 +895,10 @@ LLIMGroupChiclet::LLIMGroupChiclet(const Params& p) , mChicletIconCtrl(NULL) , mPopupMenu(NULL) { + LLIconCtrl::Params new_msg_params = p.new_message_icon; + mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); + addChild(mNewMessagesIcon); + LLChicletGroupIconCtrl::Params avatar_params = p.group_icon; mChicletIconCtrl = LLUICtrlFactory::create<LLChicletGroupIconCtrl>(avatar_params); addChild(mChicletIconCtrl); @@ -1062,6 +987,18 @@ void LLIMGroupChiclet::changed(LLGroupChange gc) } } +void LLIMGroupChiclet::updateMenuItems() +{ + if(!mPopupMenu) + return; + if(getSessionId().isNull()) + return; + + LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId()); + bool open_window_exists = open_im_floater && open_im_floater->getVisible(); + mPopupMenu->getChild<LLUICtrl>("Chat")->setEnabled(!open_window_exists); +} + BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) { if(!mPopupMenu) @@ -1071,6 +1008,7 @@ BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) if (mPopupMenu) { + updateMenuItems(); mPopupMenu->arrangeAndClear(); LLMenuGL::showPopup(this, mPopupMenu, x, y); } @@ -1124,16 +1062,10 @@ void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data) LLChicletPanel::Params::Params() : chiclet_padding("chiclet_padding") , scrolling_offset("scrolling_offset") +, scroll_button_hpad("scroll_button_hpad") +, scroll_ratio("scroll_ratio") , min_width("min_width") { - chiclet_padding = 3; - scrolling_offset = 40; - - if (!min_width.isProvided()) - { - // min_width = 4 chiclets + 3 paddings - min_width = 180 + 3*chiclet_padding; - } }; LLChicletPanel::LLChicletPanel(const Params&p) @@ -1143,6 +1075,8 @@ LLChicletPanel::LLChicletPanel(const Params&p) , mRightScrollButton(NULL) , mChicletPadding(p.chiclet_padding) , mScrollingOffset(p.scrolling_offset) +, mScrollButtonHPad(p.scroll_button_hpad) +, mScrollRatio(p.scroll_ratio) , mMinWidth(p.min_width) , mShowControls(true) { @@ -1311,7 +1245,6 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index) chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index)); arrange(); - showScrollButtonsIfNeeded(); return true; } @@ -1322,8 +1255,6 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index) void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param) { arrange(); - trimChiclets(); - showScrollButtonsIfNeeded(); } void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD¶m) @@ -1340,8 +1271,6 @@ void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it) mChicletList.erase(it); arrange(); - trimChiclets(); - showScrollButtonsIfNeeded(); } void LLChicletPanel::removeChiclet(S32 index) @@ -1434,8 +1363,6 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent ) { LLPanel::reshape(width,height,called_from_parent); - static const S32 SCROLL_BUTTON_PAD = 5; - //Needed once- to avoid error at first call of reshape() before postBuild() if(!mLeftScrollButton||!mRightScrollButton) return; @@ -1446,9 +1373,21 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent ) scroll_button_rect = mRightScrollButton->getRect(); mRightScrollButton->setRect(LLRect(width - scroll_button_rect.getWidth(),scroll_button_rect.mTop, width, scroll_button_rect.mBottom)); - mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, - height, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); + + + bool need_show_scroll = needShowScroll(); + if(need_show_scroll) + { + mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad, + height, width - scroll_button_rect.getWidth() - mScrollButtonHPad, 0)); + } + else + { + mScrollArea->setRect(LLRect(0,height, width, 0)); + } + mShowControls = width >= mMinWidth; + mScrollArea->setVisible(mShowControls); trimChiclets(); @@ -1456,13 +1395,27 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent ) } +S32 LLChicletPanel::notifyParent(const LLSD& info) +{ + if(info.has("notification")) + { + std::string str_notification = info["notification"]; + if(str_notification == "size_changes") + { + arrange(); + return 1; + } + } + return LLPanel::notifyParent(info); +} + void LLChicletPanel::arrange() { if(mChicletList.empty()) return; + //initial arrange of chicklets positions S32 chiclet_left = getChiclet(0)->getRect().mLeft; - S32 size = getChicletCount(); for( int n = 0; n < size; ++n) { @@ -1476,6 +1429,24 @@ void LLChicletPanel::arrange() chiclet_left += chiclet_width + getChicletPadding(); } + + //reset size and pos on mScrollArea + LLRect rect = getRect(); + LLRect scroll_button_rect = mLeftScrollButton->getRect(); + + bool need_show_scroll = needShowScroll(); + if(need_show_scroll) + { + mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad, + rect.getHeight(), rect.getWidth() - scroll_button_rect.getWidth() - mScrollButtonHPad, 0)); + } + else + { + mScrollArea->setRect(LLRect(0,rect.getHeight(), rect.getWidth(), 0)); + } + + trimChiclets(); + showScrollButtonsIfNeeded(); } void LLChicletPanel::trimChiclets() @@ -1493,6 +1464,17 @@ void LLChicletPanel::trimChiclets() } } +bool LLChicletPanel::needShowScroll() +{ + if(mChicletList.empty()) + return false; + + S32 chicklet_width = (*mChicletList.rbegin())->getRect().mRight - (*mChicletList.begin())->getRect().mLeft; + + return chicklet_width>getRect().getWidth(); +} + + void LLChicletPanel::showScrollButtonsIfNeeded() { bool can_scroll_left = canScrollLeft(); @@ -1620,7 +1602,7 @@ void LLChicletPanel::onRightScrollClick() void LLChicletPanel::onLeftScrollHeldDown() { S32 offset = mScrollingOffset; - mScrollingOffset = mScrollingOffset / s_scroll_ratio; + mScrollingOffset = mScrollingOffset / mScrollRatio; scrollLeft(); mScrollingOffset = offset; } @@ -1628,7 +1610,7 @@ void LLChicletPanel::onLeftScrollHeldDown() void LLChicletPanel::onRightScrollHeldDown() { S32 offset = mScrollingOffset; - mScrollingOffset = mScrollingOffset / s_scroll_ratio; + mScrollingOffset = mScrollingOffset / mScrollRatio; scrollRight(); mScrollingOffset = offset; } @@ -1690,7 +1672,7 @@ S32 LLChicletPanel::getTotalUnreadIMCount() ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// LLChicletNotificationCounterCtrl::Params::Params() -: max_displayed_count("max_displayed_count", MAX_DISPLAYED_COUNT) +: max_displayed_count("max_displayed_count", 99) { } @@ -1767,6 +1749,7 @@ LLChicletGroupIconCtrl::LLChicletGroupIconCtrl(const Params& p) : LLIconCtrl(p) , mDefaultIcon(p.default_icon) { + setValue(LLUUID::null); } void LLChicletGroupIconCtrl::setValue(const LLSD& value ) @@ -1818,20 +1801,23 @@ LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p) LLScriptChiclet::Params::Params() : icon("icon") + , new_message_icon("new_message_icon") { - // *TODO Vadim: Get rid of hardcoded values. - rect(CHICLET_RECT); - icon.rect(CHICLET_ICON_RECT); } LLScriptChiclet::LLScriptChiclet(const Params&p) : LLIMChiclet(p) , mChicletIconCtrl(NULL) { + LLIconCtrl::Params new_msg_params = p.new_message_icon; + mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); + addChild(mNewMessagesIcon); + LLIconCtrl::Params icon_params = p.icon; mChicletIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params); - // Let "new message" icon be on top, else it will be hidden behind chiclet icon. - addChildInBack(mChicletIconCtrl); + addChild(mChicletIconCtrl); + + sendChildToFront(mNewMessagesIcon); } void LLScriptChiclet::setSessionId(const LLUUID& session_id) @@ -1870,20 +1856,24 @@ BOOL LLScriptChiclet::handleMouseDown(S32 x, S32 y, MASK mask) static const std::string INVENTORY_USER_OFFER ("UserGiveItem"); LLInvOfferChiclet::Params::Params() + : icon("icon") + , new_message_icon("new_message_icon") { - // *TODO Vadim: Get rid of hardcoded values. - rect(CHICLET_RECT); - icon.rect(CHICLET_ICON_RECT); } LLInvOfferChiclet::LLInvOfferChiclet(const Params&p) : LLIMChiclet(p) , mChicletIconCtrl(NULL) { + LLIconCtrl::Params new_msg_params = p.new_message_icon; + mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); + addChild(mNewMessagesIcon); + LLChicletInvOfferIconCtrl::Params icon_params = p.icon; mChicletIconCtrl = LLUICtrlFactory::create<LLChicletInvOfferIconCtrl>(icon_params); - // Let "new message" icon be on top, else it will be hidden behind chiclet icon. - addChildInBack(mChicletIconCtrl); + addChild(mChicletIconCtrl); + + sendChildToFront(mNewMessagesIcon); } void LLInvOfferChiclet::setSessionId(const LLUUID& session_id) diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 259476c2ad..3665e4d093 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -41,7 +41,6 @@ #include "llgroupmgr.h" #include "llimview.h" -class LLVoiceControlPanel; class LLMenuGL; class LLIMFloater; @@ -52,8 +51,6 @@ class LLChicletNotificationCounterCtrl : public LLTextBox { public: - static const S32 MAX_DISPLAYED_COUNT; - struct Params : public LLInitParam::Block<Params, LLTextBox::Params> { /** @@ -217,7 +214,8 @@ public: struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> { - Optional<bool> show_counter; + Optional<bool> show_counter, + enable_counter; Params(); }; @@ -323,10 +321,7 @@ public: }; struct Params : public LLInitParam::Block<Params, LLChiclet::Params> { - Optional<std::string> new_messages_icon_name; - - Params() : new_messages_icon_name("new_messages_icon_name", "Unread_IM") - {} + Params(){} }; @@ -437,6 +432,8 @@ protected: bool mShowSpeaker; bool mCounterEnabled; + /* initial width of chiclet, should not include counter or speaker width */ + S32 mDefaultWidth; LLIconCtrl* mNewMessagesIcon; LLChicletNotificationCounterCtrl* mCounterCtrl; @@ -482,6 +479,8 @@ public: Optional<LLChicletSpeakerCtrl::Params> speaker; + Optional<LLIconCtrl::Params> new_message_icon; + Optional<bool> show_speaker; Params(); @@ -521,6 +520,7 @@ protected: /** * Enables/disables menus based on relationship with other participant. + * Enables/disables "show session" menu item depending on visible IM floater existence. */ virtual void updateMenuItems(); @@ -544,6 +544,8 @@ public: Optional<LLChicletSpeakerCtrl::Params> speaker; + Optional<LLIconCtrl::Params> new_message_icon; + Optional<bool> show_speaker; Optional<LLColor4> avatar_icon_color; @@ -614,6 +616,8 @@ public: { Optional<LLIconCtrl::Params> icon; + Optional<LLIconCtrl::Params> new_message_icon; + Params(); }; @@ -654,6 +658,8 @@ public: { Optional<LLChicletInvOfferIconCtrl::Params> icon; + Optional<LLIconCtrl::Params> new_message_icon; + Params(); }; @@ -697,6 +703,8 @@ public: Optional<LLChicletSpeakerCtrl::Params> speaker; + Optional<LLIconCtrl::Params> new_message_icon; + Optional<bool> show_speaker; Params(); @@ -752,6 +760,11 @@ protected: virtual void onMenuItemClicked(const LLSD& user_data); /** + * Enables/disables "show session" menu item depending on visible IM floater existence. + */ + virtual void updateMenuItems(); + + /** * Displays popup menu. */ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); @@ -811,6 +824,8 @@ public: void setToggleState(BOOL toggled); void setNewMessagesState(bool new_messages); + //this method should change a widget according to state of the SysWellWindow + virtual void updateWidget(bool is_window_empty); protected: @@ -916,7 +931,7 @@ protected: // methods for updating a number of unread System notifications void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); } void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); } - + /*virtual*/ void setCounter(S32 counter); S32 mUreadSystemNotifications; }; @@ -931,7 +946,9 @@ public: struct Params : public LLInitParam::Block<Params, LLPanel::Params> { Optional<S32> chiclet_padding, - scrolling_offset; + scrolling_offset, + scroll_button_hpad, + scroll_ratio; Optional<S32> min_width; @@ -1021,6 +1038,8 @@ public: S32 getTotalUnreadIMCount(); + S32 notifyParent(const LLSD& info); + protected: LLChicletPanel(const Params&p); friend class LLUICtrlFactory; @@ -1050,6 +1069,11 @@ protected: bool canScrollRight(); /** + * Returns true if we need to show scroll buttons + */ + bool needShowScroll(); + + /** * Returns true if chiclets can be scrolled left. */ bool canScrollLeft(); @@ -1143,6 +1167,8 @@ protected: S32 mChicletPadding; S32 mScrollingOffset; + S32 mScrollButtonHPad; + S32 mScrollRatio; S32 mMinWidth; bool mShowControls; static const S32 s_scroll_ratio; diff --git a/indra/newview/llcommanddispatcherlistener.cpp b/indra/newview/llcommanddispatcherlistener.cpp index 00a20de30e..91baeaf989 100644 --- a/indra/newview/llcommanddispatcherlistener.cpp +++ b/indra/newview/llcommanddispatcherlistener.cpp @@ -31,6 +31,11 @@ LLCommandDispatcherListener::LLCommandDispatcherListener(/* LLCommandDispatcher* "[\"query\"] map of parameters, as if from ?key1=val&key2=val\n" "[\"trusted\"] boolean indicating trusted browser [default true]", &LLCommandDispatcherListener::dispatch); + add("enumerate", + "Post to [\"reply\"] a map of registered LLCommandHandler instances, containing\n" + "name key and (e.g.) untrusted flag", + &LLCommandDispatcherListener::enumerate, + LLSD().with("reply", LLSD())); } void LLCommandDispatcherListener::dispatch(const LLSD& params) const @@ -45,3 +50,11 @@ void LLCommandDispatcherListener::dispatch(const LLSD& params) const LLCommandDispatcher::dispatch(params["cmd"], params["params"], params["query"], NULL, trusted_browser); } + +void LLCommandDispatcherListener::enumerate(const LLSD& params) const +{ + LLReqID reqID(params); + LLSD response(LLCommandDispatcher::enumerate()); + reqID.stamp(response); + LLEventPumps::instance().obtain(params["reply"]).post(response); +} diff --git a/indra/newview/llcommanddispatcherlistener.h b/indra/newview/llcommanddispatcherlistener.h index d0070ddd71..9bcddebcc1 100644 --- a/indra/newview/llcommanddispatcherlistener.h +++ b/indra/newview/llcommanddispatcherlistener.h @@ -23,6 +23,7 @@ public: private: void dispatch(const LLSD& params) const; + void enumerate(const LLSD& params) const; //LLCommandDispatcher* mDispatcher; }; diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index 8c7e7bea83..dc506a1692 100644 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp @@ -36,6 +36,7 @@ #include "llcommandhandler.h" #include "llnotificationsutil.h" #include "llcommanddispatcherlistener.h" +#include "stringize.h" // system includes #include <boost/tokenizer.hpp> @@ -67,6 +68,7 @@ public: bool trusted_browser); private: + friend LLSD LLCommandDispatcher::enumerate(); std::map<std::string, LLCommandHandlerInfo> mMap; }; @@ -175,3 +177,56 @@ bool LLCommandDispatcher::dispatch(const std::string& cmd, return LLCommandHandlerRegistry::instance().dispatch( cmd, params, query_map, web, trusted_browser); } + +static std::string lookup(LLCommandHandler::EUntrustedAccess value); + +LLSD LLCommandDispatcher::enumerate() +{ + LLSD response; + LLCommandHandlerRegistry& registry(LLCommandHandlerRegistry::instance()); + for (std::map<std::string, LLCommandHandlerInfo>::const_iterator chi(registry.mMap.begin()), + chend(registry.mMap.end()); + chi != chend; ++chi) + { + LLSD info; + info["untrusted"] = chi->second.mUntrustedBrowserAccess; + info["untrusted_str"] = lookup(chi->second.mUntrustedBrowserAccess); + response[chi->first] = info; + } + return response; +} + +/*------------------------------ lookup stuff ------------------------------*/ +struct symbol_info +{ + const char* name; + LLCommandHandler::EUntrustedAccess value; +}; + +#define ent(SYMBOL) \ + { \ + #SYMBOL + 28, /* skip "LLCommandHandler::UNTRUSTED_" prefix */ \ + SYMBOL \ + } + +symbol_info symbols[] = +{ + ent(LLCommandHandler::UNTRUSTED_ALLOW), // allow commands from untrusted browsers + ent(LLCommandHandler::UNTRUSTED_BLOCK), // ignore commands from untrusted browsers + ent(LLCommandHandler::UNTRUSTED_THROTTLE) // allow untrusted, but only a few per min. +}; + +#undef ent + +static std::string lookup(LLCommandHandler::EUntrustedAccess value) +{ + for (symbol_info *sii(symbols), *siend(symbols + (sizeof(symbols)/sizeof(symbols[0]))); + sii != siend; ++sii) + { + if (sii->value == value) + { + return sii->name; + } + } + return STRINGIZE("UNTRUSTED_" << value); +} diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h index 1bae6d9414..a1d4c880f5 100644 --- a/indra/newview/llcommandhandler.h +++ b/indra/newview/llcommandhandler.h @@ -34,6 +34,8 @@ #ifndef LLCOMMANDHANDLER_H #define LLCOMMANDHANDLER_H +#include "llsd.h" + /* Example: secondlife:///app/foo/<uuid> Command "foo" that takes one parameter, a UUID. @@ -103,6 +105,9 @@ public: // Execute a command registered via the above mechanism, // passing string parameters. // Returns true if command was found and executed correctly. + /// Return an LLSD::Map of registered LLCommandHandlers and associated + /// info (e.g. EUntrustedAccess). + static LLSD enumerate(); }; #endif diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 68eee061b8..e12b64a2f2 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -105,6 +105,9 @@ public: F32 getVirtualSize() const { return mVSize; } F32 getPixelArea() const { return mPixelArea; } + S32 getIndexInTex() const {return mIndexInTex ;} + void setIndexInTex(S32 index) { mIndexInTex = index ;} + void renderSetColor() const; S32 renderElements(const U16 *index_array) const; S32 renderIndexed (); @@ -236,6 +239,7 @@ private: U16 mGeomIndex; // index into draw pool U32 mIndicesCount; U32 mIndicesIndex; // index into draw pool for indices (yeah, I know!) + S32 mIndexInTex ; //previous rebuild's geometry info U16 mLastGeomCount; diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 0b27001f10..7d8bb6e104 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -98,6 +98,7 @@ LLFastTimerView::LLFastTimerView(const LLRect& rect) mHoverBarIndex = -1; FTV_NUM_TIMERS = LLFastTimer::NamedTimer::instanceCount(); mPrintStats = -1; + mAverageCyclesPerTimer = 0; } @@ -306,8 +307,9 @@ void LLFastTimerView::draw() S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f); S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f); - // HACK: casting away const. Should use setRect or some helper function instead. - const_cast<LLRect&>(getRect()).setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height); + LLRect new_rect; + new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height); + setRect(new_rect); S32 left, top, right, bottom; S32 x, y, barw, barh, dx, dy; @@ -321,6 +323,12 @@ void LLFastTimerView::draw() S32 xleft = margin; S32 ytop = margin; + mAverageCyclesPerTimer = LLFastTimer::sTimerCalls == 0 + ? 0 + : llround(lerp((F32)mAverageCyclesPerTimer, (F32)(LLFastTimer::sTimerCycles / (U64)LLFastTimer::sTimerCalls), 0.1f)); + LLFastTimer::sTimerCycles = 0; + LLFastTimer::sTimerCalls = 0; + // Draw some help { @@ -328,6 +336,10 @@ void LLFastTimerView::draw() y = height - ytop; texth = (S32)LLFontGL::getFontMonospace()->getLineHeight(); +#if TIME_FAST_TIMERS + tdesc = llformat("Cycles per timer call: %d", mAverageCyclesPerTimer); + LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); +#else char modedesc[][32] = { "2 x Average ", "Max ", @@ -342,7 +354,6 @@ void LLFastTimerView::draw() tdesc = llformat("Full bar = %s [Click to pause/reset] [SHIFT-Click to toggle]",modedesc[mDisplayMode]); LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); - textw = LLFontGL::getFontMonospace()->getWidth(tdesc); x = xleft, y -= (texth + 2); @@ -352,6 +363,7 @@ void LLFastTimerView::draw() LLFontGL::getFontMonospace()->renderUTF8(std::string("[Right-Click log selected] [ALT-Click toggle counts] [ALT-SHIFT-Click sub hidden]"), 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); +#endif y -= (texth + 2); } diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index 2bb023ab14..f5c8f23818 100644 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -91,6 +91,7 @@ private: S32 mHoverBarIndex; LLFrameTimer mHighlightTimer; S32 mPrintStats; + S32 mAverageCyclesPerTimer; }; #endif diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 832626e007..6ae6b4877a 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -162,9 +162,22 @@ public: if (!region_name.empty()) { LLToolTip::Params params; - params.message = llformat("%s\n%s (%d, %d, %d)", getLabelSelected().c_str(), region_name.c_str(), + std::string extra_message = llformat("%s (%d, %d, %d)", region_name.c_str(), mLandmarkInfoGetter.getPosX(), mLandmarkInfoGetter.getPosY(), mLandmarkInfoGetter.getPosZ()); - params.sticky_rect = calcScreenRect(); + + params.message = llformat("%s\n%s", getLabelSelected().c_str(), extra_message.c_str()); + + LLRect rect = calcScreenRect(); + LLFontGL* standart_font = LLFontGL::getFontSansSerif(); + if(standart_font) + { + S32 w = llmax((S32)(standart_font->getWidthF32(getLabelSelected())+0.5),(S32)(standart_font->getWidthF32(extra_message)+0.5)); + rect.mRight = rect.mLeft + w; + params.max_width = w; + } + + params.sticky_rect = rect; + LLToolTipMgr::instance().show(params); } return TRUE; @@ -760,9 +773,9 @@ LLButton* LLFavoritesBarCtrl::createButton(const LLPointer<LLViewerInventoryItem * WORKAROUND: * there are some problem with displaying of fonts in buttons. * Empty space (or ...) is displaying instead of last symbols, even though the width of the button is enough. - * Problem will gone, if we stretch out the button. For that reason I have to put additional 10 pixels. + * Problem will gone, if we stretch out the button. For that reason I have to put additional 20 pixels. */ - int requred_width = mFont->getWidth(item->getDisplayName()) + 10; + int requred_width = mFont->getWidth(item->getDisplayName()) + 20; int width = requred_width > def_button_width? def_button_width : requred_width; LLFavoriteLandmarkButton* fav_btn = NULL; @@ -984,7 +997,7 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) if (action == "open") { - teleport_via_landmark(item->getAssetUUID()); + onButtonClick(item->getUUID()); } else if (action == "about") { diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 6e3d5499a2..a0b2de85f0 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -51,8 +51,7 @@ #include "lluictrlfactory.h" #include "message.h" -LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(callback_t callback, - void* userdata, +LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback, BOOL allow_multiple, BOOL closeOnSelect) { @@ -60,8 +59,7 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(callback_t callback, LLFloaterAvatarPicker* floater = LLFloaterReg::showTypedInstance<LLFloaterAvatarPicker>("avatar_picker"); - floater->mCallback = callback; - floater->mCallbackUserdata = userdata; + floater->mSelectionCallback = callback; floater->setAllowMultiple(allow_multiple); floater->mNearMeListComplete = FALSE; floater->mCloseOnSelect = closeOnSelect; @@ -82,8 +80,6 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(callback_t callback, LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key) : LLFloater(key), mNumResultsReturned(0), - mCallback(NULL), - mCallbackUserdata(NULL), mNearMeListComplete(FALSE), mCloseOnSelect(FALSE) { @@ -93,29 +89,29 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key) BOOL LLFloaterAvatarPicker::postBuild() { - getChild<LLLineEditor>("Edit")->setKeystrokeCallback(editKeystroke, this); + getChild<LLLineEditor>("Edit")->setKeystrokeCallback( boost::bind(&LLFloaterAvatarPicker::editKeystroke, this, _1, _2),NULL); - childSetAction("Find", onBtnFind, this); + childSetAction("Find", boost::bind(&LLFloaterAvatarPicker::onBtnFind, this)); childDisable("Find"); - childSetAction("Refresh", onBtnRefresh, this); - childSetCommitCallback("near_me_range", onRangeAdjust, this); + childSetAction("Refresh", boost::bind(&LLFloaterAvatarPicker::onBtnRefresh, this)); + getChild<LLUICtrl>("near_me_range")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onRangeAdjust, this)); LLScrollListCtrl* searchresults = getChild<LLScrollListCtrl>("SearchResults"); - searchresults->setDoubleClickCallback(onBtnSelect, this); - childSetCommitCallback("SearchResults", onList, this); + searchresults->setDoubleClickCallback( boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this)); + searchresults->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this)); childDisable("SearchResults"); LLScrollListCtrl* nearme = getChild<LLScrollListCtrl>("NearMe"); - nearme->setDoubleClickCallback(onBtnSelect, this); - childSetCommitCallback("NearMe", onList, this); + nearme->setDoubleClickCallback(boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this)); + nearme->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this)); LLScrollListCtrl* friends = getChild<LLScrollListCtrl>("Friends"); - friends->setDoubleClickCallback(onBtnSelect, this); - childSetCommitCallback("Friends", onList, this); + friends->setDoubleClickCallback(boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this)); + getChild<LLUICtrl>("Friends")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this)); - childSetAction("ok_btn", onBtnSelect, this); + childSetAction("ok_btn", boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this)); childDisable("ok_btn"); - childSetAction("cancel_btn", onBtnClose, this); + childSetAction("cancel_btn", boost::bind(&LLFloaterAvatarPicker::onBtnClose, this)); childSetFocus("Edit"); @@ -156,10 +152,9 @@ LLFloaterAvatarPicker::~LLFloaterAvatarPicker() gFocusMgr.releaseFocusIfNeeded( this ); } -void LLFloaterAvatarPicker::onBtnFind(void* userdata) +void LLFloaterAvatarPicker::onBtnFind() { - LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata; - if(self) self->find(); + find(); } static void getSelectedAvatarData(const LLScrollListCtrl* from, std::vector<std::string>& avatar_names, std::vector<LLUUID>& avatar_ids) @@ -176,34 +171,33 @@ static void getSelectedAvatarData(const LLScrollListCtrl* from, std::vector<std: } } -void LLFloaterAvatarPicker::onBtnSelect(void* userdata) +void LLFloaterAvatarPicker::onBtnSelect() { - LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata; // If select btn not enabled then do not callback - if (!self || !self->isSelectBtnEnabled()) + if (!isSelectBtnEnabled()) return; - if(self->mCallback) + if(mSelectionCallback) { std::string acvtive_panel_name; LLScrollListCtrl* list = NULL; - LLPanel* active_panel = self->childGetVisibleTab("ResidentChooserTabs"); + LLPanel* active_panel = childGetVisibleTab("ResidentChooserTabs"); if(active_panel) { acvtive_panel_name = active_panel->getName(); } if(acvtive_panel_name == "SearchPanel") { - list = self->getChild<LLScrollListCtrl>("SearchResults"); + list = getChild<LLScrollListCtrl>("SearchResults"); } else if(acvtive_panel_name == "NearMePanel") { - list =self->getChild<LLScrollListCtrl>("NearMe"); + list = getChild<LLScrollListCtrl>("NearMe"); } else if (acvtive_panel_name == "FriendsPanel") { - list =self->getChild<LLScrollListCtrl>("Friends"); + list = getChild<LLScrollListCtrl>("Friends"); } if(list) @@ -211,50 +205,39 @@ void LLFloaterAvatarPicker::onBtnSelect(void* userdata) std::vector<std::string> avatar_names; std::vector<LLUUID> avatar_ids; getSelectedAvatarData(list, avatar_names, avatar_ids); - self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata); + mSelectionCallback(avatar_names, avatar_ids); } } - self->getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE); - self->getChild<LLScrollListCtrl>("NearMe")->deselectAllItems(TRUE); - self->getChild<LLScrollListCtrl>("Friends")->deselectAllItems(TRUE); - if(self->mCloseOnSelect) + getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE); + getChild<LLScrollListCtrl>("NearMe")->deselectAllItems(TRUE); + getChild<LLScrollListCtrl>("Friends")->deselectAllItems(TRUE); + if(mCloseOnSelect) { - self->mCloseOnSelect = FALSE; - self->closeFloater(); + mCloseOnSelect = FALSE; + closeFloater(); } } -void LLFloaterAvatarPicker::onBtnRefresh(void* userdata) +void LLFloaterAvatarPicker::onBtnRefresh() { - LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata; - if (!self) - { - return; - } - - self->getChild<LLScrollListCtrl>("NearMe")->deleteAllItems(); - self->getChild<LLScrollListCtrl>("NearMe")->setCommentText(self->getString("searching")); - self->mNearMeListComplete = FALSE; + getChild<LLScrollListCtrl>("NearMe")->deleteAllItems(); + getChild<LLScrollListCtrl>("NearMe")->setCommentText(getString("searching")); + mNearMeListComplete = FALSE; } -void LLFloaterAvatarPicker::onBtnClose(void* userdata) +void LLFloaterAvatarPicker::onBtnClose() { - LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata; - if(self) self->closeFloater(); + closeFloater(); } -void LLFloaterAvatarPicker::onRangeAdjust(LLUICtrl* source, void* data) +void LLFloaterAvatarPicker::onRangeAdjust() { - LLFloaterAvatarPicker::onBtnRefresh(data); + onBtnRefresh(); } -void LLFloaterAvatarPicker::onList(LLUICtrl* ctrl, void* userdata) +void LLFloaterAvatarPicker::onList() { - LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata; - if (self) - { - self->childSetEnabled("ok_btn", self->isSelectBtnEnabled()); - } + childSetEnabled("ok_btn", isSelectBtnEnabled()); } void LLFloaterAvatarPicker::populateNearMe() @@ -297,7 +280,7 @@ void LLFloaterAvatarPicker::populateNearMe() childEnable("NearMe"); childEnable("ok_btn"); near_me_scroller->selectFirstItem(); - onList(near_me_scroller, this); + onList(); near_me_scroller->setFocus(TRUE); } @@ -451,7 +434,7 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void* { floater->childEnable("ok_btn"); search_results->selectFirstItem(); - floater->onList(search_results, floater); + floater->onList(); search_results->setFocus(TRUE); } } @@ -459,8 +442,7 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void* //static void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller, void* user_data) { - LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)user_data; - self->childSetEnabled("Find", caller->getText().size() >= 3); + childSetEnabled("Find", caller->getText().size() >= 3); } // virtual @@ -470,11 +452,11 @@ BOOL LLFloaterAvatarPicker::handleKeyHere(KEY key, MASK mask) { if (childHasFocus("Edit")) { - onBtnFind(this); + onBtnFind(); } else { - onBtnSelect(this); + onBtnSelect(); } return TRUE; } diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index 13e491834e..e35466cec8 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -43,11 +43,10 @@ public: typedef boost::signals2::signal<bool(const std::vector<LLUUID>&), boost_boolean_combiner> validate_signal_t; typedef validate_signal_t::slot_type validate_callback_t; - // Call this to select an avatar. // The callback function will be called with an avatar name and UUID. - typedef void(*callback_t)(const std::vector<std::string>&, const std::vector<LLUUID>&, void*); - static LLFloaterAvatarPicker* show(callback_t callback, - void* userdata, + typedef boost::function<void (const std::vector<std::string>&, const std::vector<LLUUID>&)> select_callback_t; + // Call this to select an avatar. + static LLFloaterAvatarPicker* show(select_callback_t callback, BOOL allow_multiple = FALSE, BOOL closeOnSelect = FALSE); @@ -61,16 +60,16 @@ public: static void processAvatarPickerReply(class LLMessageSystem* msg, void**); private: - static void editKeystroke(class LLLineEditor* caller, void* user_data); + void editKeystroke(class LLLineEditor* caller, void* user_data); - static void onBtnFind(void* userdata); - static void onBtnSelect(void* userdata); - static void onBtnRefresh(void* userdata); - static void onRangeAdjust(LLUICtrl* source, void* data); - static void onBtnClose(void* userdata); - static void onList(class LLUICtrl* ctrl, void* userdata); - void onTabChanged(); - bool isSelectBtnEnabled(); + void onBtnFind(); + void onBtnSelect(); + void onBtnRefresh(); + void onRangeAdjust(); + void onBtnClose(); + void onList(); + void onTabChanged(); + bool isSelectBtnEnabled(); void populateNearMe(); void populateFriend(); @@ -87,9 +86,8 @@ private: BOOL mNearMeListComplete; BOOL mCloseOnSelect; - void (*mCallback)(const std::vector<std::string>& name, const std::vector<LLUUID>& id, void* userdata); - void* mCallbackUserdata; validate_signal_t mOkButtonValidateSignal; + select_callback_t mSelectionCallback; }; #endif diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp index 1b14ca573a..9108cfb72b 100644 --- a/indra/newview/llfloaterchatterbox.cpp +++ b/indra/newview/llfloaterchatterbox.cpp @@ -44,6 +44,7 @@ #include "llviewercontrol.h" #include "llvoicechannel.h" #include "llimpanel.h" +#include "llimview.h" // // LLFloaterMyFriends diff --git a/indra/newview/llfloaterchatterbox.h b/indra/newview/llfloaterchatterbox.h index 3929e6e36c..ab44281d81 100644 --- a/indra/newview/llfloaterchatterbox.h +++ b/indra/newview/llfloaterchatterbox.h @@ -36,8 +36,8 @@ #define LL_LLFLOATERCHATTERBOX_H #include "llfloater.h" +#include "llmultifloater.h" #include "llstring.h" -#include "llimview.h" #include "llimpanel.h" class LLTabContainer; diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 56291c57a6..ccc5cab85a 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -572,8 +572,7 @@ void LLPanelFriends::onClickIM(void* user_data) // static void LLPanelFriends::onPickAvatar(const std::vector<std::string>& names, - const std::vector<LLUUID>& ids, - void* ) + const std::vector<LLUUID>& ids) { if (names.empty()) return; if (ids.empty()) return; @@ -585,7 +584,7 @@ void LLPanelFriends::onClickAddFriend(void* user_data) { LLPanelFriends* panelp = (LLPanelFriends*)user_data; LLFloater* root_floater = gFloaterView->getParentFloater(panelp); - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(onPickAvatar, user_data, FALSE, TRUE); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelFriends::onPickAvatar, _1,_2), FALSE, TRUE); if (root_floater) { root_floater->addDependentFloater(picker); diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h index 9c6660c0dc..0042da48d3 100644 --- a/indra/newview/llfloaterfriends.h +++ b/indra/newview/llfloaterfriends.h @@ -116,7 +116,7 @@ private: static void onSelectName(LLUICtrl* ctrl, void* user_data); static bool callbackAddFriend(const LLSD& notification, const LLSD& response); static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response); - static void onPickAvatar(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* user_data); + static void onPickAvatar(const std::vector<std::string>& names, const std::vector<LLUUID>& ids); static void onMaximumSelect(); static void onClickIM(void* user_data); diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index e1409b8ad5..c2b0bd18fa 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -1165,7 +1165,7 @@ bool LLPanelObjectTools::callbackSimWideDeletes( const LLSD& notification, const void LLPanelObjectTools::onClickSet() { // grandparent is a floater, which can have a dependent - gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarID, this)); + gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelObjectTools::callbackAvatarID, this, _1,_2))); } void LLPanelObjectTools::onClickSetBySelection(void* data) @@ -1189,14 +1189,12 @@ void LLPanelObjectTools::onClickSetBySelection(void* data) panelp->childSetValue("target_avatar_name", name); } -// static -void LLPanelObjectTools::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data) +void LLPanelObjectTools::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids) { - LLPanelObjectTools* object_tools = (LLPanelObjectTools*) data; if (ids.empty() || names.empty()) return; - object_tools->mTargetAvatar = ids[0]; - object_tools->childSetValue("target_avatar_name", names[0]); - object_tools->refresh(); + mTargetAvatar = ids[0]; + childSetValue("target_avatar_name", names[0]); + refresh(); } void LLPanelObjectTools::onChangeAnything() diff --git a/indra/newview/llfloatergodtools.h b/indra/newview/llfloatergodtools.h index ebab1fde11..ef5ce02749 100644 --- a/indra/newview/llfloatergodtools.h +++ b/indra/newview/llfloatergodtools.h @@ -234,7 +234,7 @@ public: void onChangeAnything(); void onApplyChanges(); void onClickSet(); - static void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data); + void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids); void onClickDeletePublicOwnedBy(); void onClickDeleteAllScriptedOwnedBy(); void onClickDeleteAllOwnedBy(); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 81322abbf7..598a13de15 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -52,6 +52,7 @@ #include "llfloateravatarpicker.h" #include "llfloaterauction.h" #include "llfloatergroups.h" +#include "llfloaterscriptlimits.h" #include "llavataractions.h" #include "lllineeditor.h" #include "llnamelistctrl.h" @@ -148,6 +149,10 @@ void send_parcel_select_objects(S32 parcel_local_id, U32 return_type, msg->sendReliable(region->getHost()); } +LLParcel* LLFloaterLand::getCurrentSelectedParcel() +{ + return mParcel->getParcel(); +}; //static LLPanelLandObjects* LLFloaterLand::getCurrentPanelLandObjects() @@ -421,6 +426,9 @@ BOOL LLPanelLandGeneral::postBuild() mBtnBuyLand = getChild<LLButton>("Buy Land..."); mBtnBuyLand->setClickedCallback(onClickBuyLand, (void*)&BUY_PERSONAL_LAND); + mBtnScriptLimits = getChild<LLButton>("Scripts..."); + mBtnScriptLimits->setClickedCallback(onClickScriptLimits, this); + mBtnBuyGroupLand = getChild<LLButton>("Buy For Group..."); mBtnBuyGroupLand->setClickedCallback(onClickBuyLand, (void*)&BUY_GROUP_LAND); @@ -508,6 +516,7 @@ void LLPanelLandGeneral::refresh() mTextDwell->setText(LLStringUtil::null); mBtnBuyLand->setEnabled(FALSE); + mBtnScriptLimits->setEnabled(FALSE); mBtnBuyGroupLand->setEnabled(FALSE); mBtnReleaseLand->setEnabled(FALSE); mBtnReclaimLand->setEnabled(FALSE); @@ -715,6 +724,8 @@ void LLPanelLandGeneral::refresh() mBtnBuyLand->setEnabled( LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false)); + mBtnScriptLimits->setEnabled(true); +// LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false)); mBtnBuyGroupLand->setEnabled( LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, true)); @@ -854,6 +865,17 @@ void LLPanelLandGeneral::onClickBuyLand(void* data) LLViewerParcelMgr::getInstance()->startBuyLand(*for_group); } +// static +void LLPanelLandGeneral::onClickScriptLimits(void* data) +{ + LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; + LLParcel* parcel = panelp->mParcel->getParcel(); + if(parcel != NULL) + { + LLFloaterReg::showInstance("script_limits"); + } +} + BOOL LLPanelLandGeneral::enableDeedToGroup(void* data) { LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; @@ -2262,9 +2284,9 @@ BOOL LLPanelLandAccess::postBuild() childSetCommitCallback("PriceSpin", onCommitAny, this); childSetCommitCallback("HoursSpin", onCommitAny, this); - childSetAction("add_allowed", onClickAddAccess, this); + childSetAction("add_allowed", boost::bind(&LLPanelLandAccess::onClickAddAccess, this)); childSetAction("remove_allowed", onClickRemoveAccess, this); - childSetAction("add_banned", onClickAddBanned, this); + childSetAction("add_banned", boost::bind(&LLPanelLandAccess::onClickAddBanned, this)); childSetAction("remove_banned", onClickRemoveBanned, this); mListAccess = getChild<LLNameListCtrl>("AccessList"); @@ -2672,29 +2694,22 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata) self->refresh(); } -// static -void LLPanelLandAccess::onClickAddAccess(void* data) +void LLPanelLandAccess::onClickAddAccess() { - LLPanelLandAccess* panelp = (LLPanelLandAccess*)data; - if (panelp) - { - gFloaterView->getParentFloater(panelp)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarCBAccess, data) ); - } + gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1,_2)) ); } -// static -void LLPanelLandAccess::callbackAvatarCBAccess(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata) +void LLPanelLandAccess::callbackAvatarCBAccess(const std::vector<std::string>& names, const std::vector<LLUUID>& ids) { - LLPanelLandAccess* panelp = (LLPanelLandAccess*)userdata; if (!names.empty() && !ids.empty()) { LLUUID id = ids[0]; - LLParcel* parcel = panelp->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (parcel) { parcel->addToAccessList(id, 0); LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(AL_ACCESS); - panelp->refresh(); + refresh(); } } } @@ -2723,25 +2738,23 @@ void LLPanelLandAccess::onClickRemoveAccess(void* data) } // static -void LLPanelLandAccess::onClickAddBanned(void* data) +void LLPanelLandAccess::onClickAddBanned() { - LLPanelLandAccess* panelp = (LLPanelLandAccess*)data; - gFloaterView->getParentFloater(panelp)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarCBBanned, data) ); + gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1,_2))); } // static -void LLPanelLandAccess::callbackAvatarCBBanned(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata) +void LLPanelLandAccess::callbackAvatarCBBanned(const std::vector<std::string>& names, const std::vector<LLUUID>& ids) { - LLPanelLandAccess* panelp = (LLPanelLandAccess*)userdata; if (!names.empty() && !ids.empty()) { LLUUID id = ids[0]; - LLParcel* parcel = panelp->mParcel->getParcel(); + LLParcel* parcel = mParcel->getParcel(); if (parcel) { parcel->addToBanList(id, 0); LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(AL_BAN); - panelp->refresh(); + refresh(); } } } diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index f7fb978c2a..d7d02ba1a3 100644 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -70,6 +70,7 @@ class LLPanelLandAccess; class LLPanelLandBan; class LLPanelLandRenters; class LLPanelLandCovenant; +class LLParcel; class LLFloaterLand : public LLFloater @@ -80,7 +81,9 @@ public: static LLPanelLandObjects* getCurrentPanelLandObjects(); static LLPanelLandCovenant* getCurrentPanelLandCovenant(); - + + LLParcel* getCurrentSelectedParcel(); + virtual void onOpen(const LLSD& key); virtual BOOL postBuild(); @@ -146,6 +149,7 @@ public: static BOOL enableDeedToGroup(void*); static void onClickDeed(void*); static void onClickBuyLand(void* data); + static void onClickScriptLimits(void* data); static void onClickRelease(void*); static void onClickReclaim(void*); static void onClickBuyPass(void* deselect_when_done); @@ -215,6 +219,7 @@ protected: LLTextBox* mTextDwell; LLButton* mBtnBuyLand; + LLButton* mBtnScriptLimits; LLButton* mBtnBuyGroupLand; // these buttons share the same location, but @@ -362,14 +367,15 @@ public: static void onCommitPublicAccess(LLUICtrl* ctrl, void *userdata); static void onCommitAny(LLUICtrl* ctrl, void *userdata); - static void onClickAddAccess(void*); - static void callbackAvatarCBAccess(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata); static void onClickRemoveAccess(void*); - static void onClickAddBanned(void*); - static void callbackAvatarCBBanned(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata); static void onClickRemoveBanned(void*); virtual BOOL postBuild(); + + void onClickAddAccess(); + void onClickAddBanned(); + void callbackAvatarCBBanned(const std::vector<std::string>& names, const std::vector<LLUUID>& ids); + void callbackAvatarCBAccess(const std::vector<std::string>& names, const std::vector<LLUUID>& ids); protected: LLNameListCtrl* mListAccess; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index ff568a11a9..11dd48056c 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -103,15 +103,10 @@ #include "llworld.h" #include "pipeline.h" #include "lluictrlfactory.h" -#include "llboost.h" #include "llviewermedia.h" #include "llpluginclassmedia.h" #include "llteleporthistorystorage.h" -#include <boost/regex.hpp> - -//RN temporary includes for resolution switching -#include "llglheaders.h" const F32 MAX_USER_FAR_CLIP = 512.f; const F32 MIN_USER_FAR_CLIP = 64.f; @@ -193,7 +188,6 @@ bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater); bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater); -bool extractWindowSizeFromString(const std::string& instr, U32 &width, U32 &height); void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator); viewer_media_t get_web_media() @@ -273,23 +267,6 @@ bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFl } -// Extract from strings of the form "<width> x <height>", e.g. "640 x 480". -bool extractWindowSizeFromString(const std::string& instr, U32 &width, U32 &height) -{ - using namespace boost; - cmatch what; - const regex expression("([0-9]+) x ([0-9]+)"); - if (regex_match(instr.c_str(), what, expression)) - { - width = atoi(what[1].first); - height = atoi(what[2].first); - return true; - } - - width = height = 0; - return false; -} - void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator) { numerator = 0; @@ -499,13 +476,6 @@ void LLFloaterPreference::apply() } applyResolution(); - - // Only set window size if we're not in fullscreen mode - if(!gSavedSettings.getBOOL("WindowFullScreen")) - { - applyWindowSize(); - } - } void LLFloaterPreference::cancel() @@ -760,8 +730,9 @@ void LLFloaterPreference::onClickResetCache() { gSavedSettings.setString("NewCacheLocation", ""); gSavedSettings.setString("NewCacheLocationTopFolder", ""); - LLNotificationsUtil::add("CacheWillBeMoved"); } + + LLNotificationsUtil::add("CacheWillBeMoved"); std::string cache_location = gDirUtilp->getCacheDir(true); gSavedSettings.setString("CacheLocation", cache_location); std::string top_folder(gDirUtilp->getBaseFileName(cache_location)); @@ -1263,20 +1234,6 @@ void LLFloaterPreference::onKeystrokeAspectRatio() getChild<LLCheckBoxCtrl>("aspect_auto_detect")->set(FALSE); } -void LLFloaterPreference::applyWindowSize() -{ - LLComboBox* ctrl_windowSize = getChild<LLComboBox>("windowsize combo"); - if (ctrl_windowSize->getVisible() && (ctrl_windowSize->getCurrentIndex() != -1)) - { - U32 width = 0; - U32 height = 0; - if (extractWindowSizeFromString(ctrl_windowSize->getValue().asString().c_str(), width,height)) - { - LLViewerWindow::movieSize(width, height); - } - } -} - void LLFloaterPreference::applyResolution() { LLComboBox* ctrl_aspect_ratio = getChild<LLComboBox>( "aspect_ratio"); @@ -1344,36 +1301,7 @@ void LLFloaterPreference::applyResolution() refresh(); } -void LLFloaterPreference::initWindowSizeControls(LLPanel* panelp) -{ - // Window size - // mWindowSizeLabel = getChild<LLTextBox>("WindowSizeLabel"); - LLComboBox* ctrl_window_size = panelp->getChild<LLComboBox>("windowsize combo"); - - // Look to see if current window size matches existing window sizes, if so then - // just set the selection value... - const U32 height = gViewerWindow->getWindowHeightRaw(); - const U32 width = gViewerWindow->getWindowWidthRaw(); - for (S32 i=0; i < ctrl_window_size->getItemCount(); i++) - { - U32 height_test = 0; - U32 width_test = 0; - ctrl_window_size->setCurrentByIndex(i); - if (extractWindowSizeFromString(ctrl_window_size->getValue().asString(), width_test, height_test)) - { - if ((height_test == height) && (width_test == width)) - { - return; - } - } - } - // ...otherwise, add a new entry with the current window height/width. - LLUIString resolution_label = panelp->getString("resolution_format"); - resolution_label.setArg("[RES_X]", llformat("%d", width)); - resolution_label.setArg("[RES_Y]", llformat("%d", height)); - ctrl_window_size->add(resolution_label, ADD_TOP); - ctrl_window_size->setCurrentByIndex(0); -} + void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param) @@ -1432,53 +1360,8 @@ BOOL LLPanelPreference::postBuild() if(hasChild("aspect_ratio")) { - //============================================================================ - // Resolution -/* - S32 num_resolutions = 0; - LLWindow::LLWindowResolution* supported_resolutions = gViewerWindow->getWindow()->getSupportedResolutions(num_resolutions); - - S32 fullscreen_mode = num_resolutions - 1; - - LLComboBox*ctrl_full_screen = getChild<LLComboBox>( "fullscreen combo"); - LLUIString resolution_label = getString("resolution_format"); - - for (S32 i = 0; i < num_resolutions; i++) - { - resolution_label.setArg("[RES_X]", llformat("%d", supported_resolutions[i].mWidth)); - resolution_label.setArg("[RES_Y]", llformat("%d", supported_resolutions[i].mHeight)); - ctrl_full_screen->add( resolution_label, ADD_BOTTOM ); - } - - { - BOOL targetFullscreen; - S32 targetWidth; - S32 targetHeight; - - gViewerWindow->getTargetWindow(targetFullscreen, targetWidth, targetHeight); - - if (targetFullscreen) - { - fullscreen_mode = 0; // default to 800x600 - for (S32 i = 0; i < num_resolutions; i++) - { - if (targetWidth == supported_resolutions[i].mWidth - && targetHeight == supported_resolutions[i].mHeight) - { - fullscreen_mode = i; - } - } - ctrl_full_screen->setCurrentByIndex(fullscreen_mode); - } - else - { - // set to windowed mode - //fullscreen_mode = mCtrlFullScreen->getItemCount() - 1; - ctrl_full_screen->setCurrentByIndex(0); - } - } - */ - LLFloaterPreference::initWindowSizeControls(this); + // We used to set up fullscreen resolution and window size + // controls here, see LLFloaterWindowSize::initWindowSizeControls() if (gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio")) { diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 94108cb79a..74a53d673c 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -130,16 +130,12 @@ public: void onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name); void onKeystrokeAspectRatio(); // void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator); -// bool extractWindowSizeFromString(const std::string& instr, U32 &width, U32 &height); void onCommitAutoDetectAspect(); void applyResolution(); - void applyWindowSize(); void applyUIColor(LLUICtrl* ctrl, const LLSD& param); void getUIColor(LLUICtrl* ctrl, const LLSD& param); - static void initWindowSizeControls(LLPanel* panelp); - void buildPopupLists(); static void refreshSkin(void* data); static void cleanupBadSetting(); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 496fa62d05..c4b87c1b2d 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -586,7 +586,7 @@ BOOL LLPanelRegionGeneralInfo::postBuild() initCtrl("restrict_pushobject"); initCtrl("block_parcel_search_check"); - childSetAction("kick_btn", onClickKick, this); + childSetAction("kick_btn", boost::bind(&LLPanelRegionGeneralInfo::onClickKick, this)); childSetAction("kick_all_btn", onClickKickAll, this); childSetAction("im_btn", onClickMessage, this); // childSetAction("manage_telehub_btn", onClickManageTelehub, this); @@ -594,27 +594,22 @@ BOOL LLPanelRegionGeneralInfo::postBuild() return LLPanelRegionInfo::postBuild(); } -// static -void LLPanelRegionGeneralInfo::onClickKick(void* userdata) +void LLPanelRegionGeneralInfo::onClickKick() { llinfos << "LLPanelRegionGeneralInfo::onClickKick" << llendl; - LLPanelRegionGeneralInfo* panelp = (LLPanelRegionGeneralInfo*)userdata; // this depends on the grandparent view being a floater // in order to set up floater dependency - LLFloater* parent_floater = gFloaterView->getParentFloater(panelp); - LLFloater* child_floater = LLFloaterAvatarPicker::show(onKickCommit, userdata, FALSE, TRUE); + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1,_2), FALSE, TRUE); parent_floater->addDependentFloater(child_floater); } -// static -void LLPanelRegionGeneralInfo::onKickCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata) +void LLPanelRegionGeneralInfo::onKickCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids) { if (names.empty() || ids.empty()) return; if(ids[0].notNull()) { - LLPanelRegionGeneralInfo* self = (LLPanelRegionGeneralInfo*)userdata; - if(!self) return; strings_t strings; // [0] = our agent id // [1] = target agent id @@ -626,7 +621,7 @@ void LLPanelRegionGeneralInfo::onKickCommit(const std::vector<std::string>& name strings.push_back(strings_t::value_type(buffer)); LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - self->sendEstateOwnerMessage(gMessageSystem, "teleporthomeuser", invoice, strings); + sendEstateOwnerMessage(gMessageSystem, "teleporthomeuser", invoice, strings); } } @@ -790,7 +785,7 @@ BOOL LLPanelRegionDebugInfo::postBuild() initCtrl("disable_collisions_check"); initCtrl("disable_physics_check"); - childSetAction("choose_avatar_btn", onClickChooseAvatar, this); + childSetAction("choose_avatar_btn", boost::bind(&LLPanelRegionDebugInfo::onClickChooseAvatar, this)); childSetAction("return_btn", onClickReturn, this); childSetAction("top_colliders_btn", onClickTopColliders, this); childSetAction("top_scripts_btn", onClickTopScripts, this); @@ -842,19 +837,18 @@ BOOL LLPanelRegionDebugInfo::sendUpdate() return TRUE; } -void LLPanelRegionDebugInfo::onClickChooseAvatar(void* data) +void LLPanelRegionDebugInfo::onClickChooseAvatar() { - LLFloaterAvatarPicker::show(callbackAvatarID, data, FALSE, TRUE); + LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), FALSE, TRUE); } -// static -void LLPanelRegionDebugInfo::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data) + +void LLPanelRegionDebugInfo::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids) { - LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*) data; if (ids.empty() || names.empty()) return; - self->mTargetAvatar = ids[0]; - self->childSetValue("target_avatar_name", LLSD(names[0])); - self->refreshFromRegion( gAgent.getRegion() ); + mTargetAvatar = ids[0]; + childSetValue("target_avatar_name", LLSD(names[0])); + refreshFromRegion( gAgent.getRegion() ); } // static @@ -1528,18 +1522,16 @@ struct LLKickFromEstateInfo LLUUID mAgentID; }; -void LLPanelEstateInfo::onClickKickUser(void *user_data) +void LLPanelEstateInfo::onClickKickUser() { - LLPanelEstateInfo* panelp = (LLPanelEstateInfo*)user_data; - // this depends on the grandparent view being a floater // in order to set up floater dependency - LLFloater* parent_floater = gFloaterView->getParentFloater(panelp); - LLFloater* child_floater = LLFloaterAvatarPicker::show(LLPanelEstateInfo::onKickUserCommit, user_data, FALSE, TRUE); + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1, _2), FALSE, TRUE); parent_floater->addDependentFloater(child_floater); } -void LLPanelEstateInfo::onKickUserCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata) +void LLPanelEstateInfo::onKickUserCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids) { if (names.empty() || ids.empty()) return; @@ -1550,12 +1542,9 @@ void LLPanelEstateInfo::onKickUserCommit(const std::vector<std::string>& names, return; } - LLPanelEstateInfo* self = (LLPanelEstateInfo*)userdata; - if(!self) return; - //keep track of what user they want to kick and other misc info LLKickFromEstateInfo *kick_info = new LLKickFromEstateInfo(); - kick_info->mEstatePanelp = self; + kick_info->mEstatePanelp = this; kick_info->mAgentID = ids[0]; //Bring up a confirmation dialog @@ -1563,7 +1552,7 @@ void LLPanelEstateInfo::onKickUserCommit(const std::vector<std::string>& names, args["EVIL_USER"] = names[0]; LLSD payload; payload["agent_id"] = ids[0]; - LLNotificationsUtil::add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, self, _1, _2)); + LLNotificationsUtil::add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, this, _1, _2)); } @@ -1727,7 +1716,7 @@ bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& res LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]); // avatar picker yes multi-select, yes close-on-select - LLFloaterAvatarPicker::show(accessAddCore3, (void*)change_info, TRUE, TRUE); + LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, _2, (void*)change_info), TRUE, TRUE); return false; } @@ -2107,7 +2096,7 @@ BOOL LLPanelEstateInfo::postBuild() childSetAction("add_estate_manager_btn", onClickAddEstateManager, this); childSetAction("remove_estate_manager_btn", onClickRemoveEstateManager, this); childSetAction("message_estate_btn", onClickMessageEstate, this); - childSetAction("kick_user_from_estate_btn", onClickKickUser, this); + childSetAction("kick_user_from_estate_btn", boost::bind(&LLPanelEstateInfo::onClickKickUser, this)); childSetAction("WLEditSky", onClickEditSky, this); childSetAction("WLEditDayCycle", onClickEditDayCycle, this); diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index a21b96bf16..8d315bdb78 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -167,8 +167,8 @@ public: protected: virtual BOOL sendUpdate(); - static void onClickKick(void* userdata); - static void onKickCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata); + void onClickKick(); + void onKickCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids); static void onClickKickAll(void* userdata); bool onKickAllCommit(const LLSD& notification, const LLSD& response); static void onClickMessage(void* userdata); @@ -192,8 +192,8 @@ public: protected: virtual BOOL sendUpdate(); - static void onClickChooseAvatar(void*); - static void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data); + void onClickChooseAvatar(); + void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids); static void onClickReturn(void *); bool callbackReturn(const LLSD& notification, const LLSD& response); static void onClickTopColliders(void*); @@ -275,7 +275,7 @@ public: static void onClickRemoveBannedAgent(void* user_data); static void onClickAddEstateManager(void* user_data); static void onClickRemoveEstateManager(void* user_data); - static void onClickKickUser(void* userdata); + void onClickKickUser(); // Group picker callback is different, can't use core methods below bool addAllowedGroup(const LLSD& notification, const LLSD& response); @@ -296,7 +296,7 @@ public: // Send the actual EstateOwnerRequest "estateaccessdelta" message static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id); - static void onKickUserCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata); + void onKickUserCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids); static void onClickMessageEstate(void* data); bool onMessageCommit(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 9f3dcae8ef..e0f2fca580 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -57,7 +57,6 @@ #include "llfloaterreg.h" #include "lltexturectrl.h" #include "llscrolllistctrl.h" -#include "llimview.h" #include "lldispatcher.h" #include "llviewerobject.h" #include "llviewerregion.h" @@ -173,7 +172,7 @@ BOOL LLFloaterReporter::postBuild() std::string("tool_face_active.tga") ); childSetAction("pick_btn", onClickObjPicker, this); - childSetAction("select_abuser", onClickSelectAbuser, this); + childSetAction("select_abuser", boost::bind(&LLFloaterReporter::onClickSelectAbuser, this)); childSetAction("send_btn", onClickSend, this); childSetAction("cancel_btn", onClickCancel, this); @@ -307,26 +306,20 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id) } -// static -void LLFloaterReporter::onClickSelectAbuser(void *userdata) +void LLFloaterReporter::onClickSelectAbuser() { - LLFloaterReporter *self = (LLFloaterReporter *)userdata; - - gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarID, userdata, FALSE, TRUE )); + gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE )); } -// static -void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data) +void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids) { - LLFloaterReporter* self = (LLFloaterReporter*) data; - if (ids.empty() || names.empty()) return; - self->childSetText("abuser_name_edit", names[0] ); + childSetText("abuser_name_edit", names[0] ); - self->mAbuserID = ids[0]; + mAbuserID = ids[0]; - self->refresh(); + refresh(); } diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h index a3776f3d27..cc2dfb2f98 100644 --- a/indra/newview/llfloaterreporter.h +++ b/indra/newview/llfloaterreporter.h @@ -97,7 +97,7 @@ public: static void onClickSend (void *userdata); static void onClickCancel (void *userdata); static void onClickObjPicker (void *userdata); - static void onClickSelectAbuser (void *userdata); + void onClickSelectAbuser (); static void closePickTool (void *userdata); static void uploadDoneCallback(const LLUUID &uuid, void* user_data, S32 result, LLExtStat ext_status); static void addDescription(const std::string& description, LLMeanCollisionData *mcd = NULL); @@ -120,7 +120,7 @@ private: void setPosBox(const LLVector3d &pos); void enableControls(BOOL own_avatar); void getObjectInfo(const LLUUID& object_id); - static void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data); + void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids); private: EReportType mReportType; diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp new file mode 100644 index 0000000000..3042fbc6ec --- /dev/null +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -0,0 +1,1061 @@ +/** + * @file llfloaterscriptlimits.cpp + * @author Gabriel Lee + * @brief Implementation of the region info and controls floater and panels. + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfloaterscriptlimits.h" + +#include "llsdutil.h" +#include "llsdutil_math.h" +#include "message.h" + +#include "llagent.h" +#include "llfloateravatarpicker.h" +#include "llfloaterland.h" +#include "llfloaterreg.h" +#include "llregionhandle.h" +#include "llscrolllistctrl.h" +#include "llscrolllistitem.h" +#include "llparcel.h" +#include "lltabcontainer.h" +#include "lltracker.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "lluictrlfactory.h" +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" +#include "llviewerwindow.h" + +///---------------------------------------------------------------------------- +/// LLFloaterScriptLimits +///---------------------------------------------------------------------------- + +// due to server side bugs the full summary display is not possible +// until they are fixed this define creates a simple version of the +// summary which only shows available & correct information +#define USE_SIMPLE_SUMMARY + +LLFloaterScriptLimits::LLFloaterScriptLimits(const LLSD& seed) + : LLFloater(seed) +{ +} + +BOOL LLFloaterScriptLimits::postBuild() +{ + // a little cheap and cheerful - if there's an about land panel open default to showing parcel info, + // otherwise default to showing attachments (avatar appearance) + bool selectParcelPanel = false; + + LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land"); + if(instance) + { + if(instance->isShown()) + { + selectParcelPanel = true; + } + } + + mTab = getChild<LLTabContainer>("scriptlimits_panels"); + + // contruct the panels + LLPanelScriptLimitsRegionMemory* panel_memory; + panel_memory = new LLPanelScriptLimitsRegionMemory; + mInfoPanels.push_back(panel_memory); + + LLUICtrlFactory::getInstance()->buildPanel(panel_memory, "panel_script_limits_region_memory.xml"); + mTab->addTabPanel(panel_memory); + + LLPanelScriptLimitsRegionURLs* panel_urls = new LLPanelScriptLimitsRegionURLs; + mInfoPanels.push_back(panel_urls); + LLUICtrlFactory::getInstance()->buildPanel(panel_urls, "panel_script_limits_region_urls.xml"); + mTab->addTabPanel(panel_urls); + + LLPanelScriptLimitsAttachment* panel_attachments = new LLPanelScriptLimitsAttachment; + mInfoPanels.push_back(panel_attachments); + LLUICtrlFactory::getInstance()->buildPanel(panel_attachments, "panel_script_limits_my_avatar.xml"); + mTab->addTabPanel(panel_attachments); + + if(selectParcelPanel) + { + mTab->selectTab(0); + } + else + { + mTab->selectTab(2); + } + + return TRUE; +} + +LLFloaterScriptLimits::~LLFloaterScriptLimits() +{ +} + +// public +void LLFloaterScriptLimits::refresh() +{ + for(info_panels_t::iterator iter = mInfoPanels.begin(); + iter != mInfoPanels.end(); ++iter) + { + (*iter)->refresh(); + } +} + + +///---------------------------------------------------------------------------- +// Base class for panels +///---------------------------------------------------------------------------- + +LLPanelScriptLimitsInfo::LLPanelScriptLimitsInfo() + : LLPanel() +{ +} + + +// virtual +BOOL LLPanelScriptLimitsInfo::postBuild() +{ + refresh(); + return TRUE; +} + +// virtual +void LLPanelScriptLimitsInfo::updateChild(LLUICtrl* child_ctr) +{ +} + +///---------------------------------------------------------------------------- +// Responders +///---------------------------------------------------------------------------- + +void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content) +{ + // at this point we have an llsd which should contain ether one or two urls to the services we want. + // first we look for the details service: + if(content.has("ScriptResourceDetails")) + { + LLHTTPClient::get(content["ScriptResourceDetails"], new fetchScriptLimitsRegionDetailsResponder(mInfo)); + } + else + { + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); + if(!instance) + { + llinfos << "Failed to get llfloaterscriptlimits instance" << llendl; + } + else + { + +// temp - only show info if we get details - there's nothing to show if not until the sim gets fixed +#ifdef USE_SIMPLE_SUMMARY + + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + std::string msg = LLTrans::getString("ScriptLimitsRequestDontOwnParcel"); + panel_memory->childSetValue("loading_text", LLSD(msg)); + LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); + panel_urls->childSetValue("loading_text", LLSD(msg)); + + // intentional early out as we dont want the resource summary if we are using the "simple summary" + // and the details are missing + return; +#endif + } + } + + // then the summary service: + if(content.has("ScriptResourceSummary")) + { + LLHTTPClient::get(content["ScriptResourceSummary"], new fetchScriptLimitsRegionSummaryResponder(mInfo)); + } +} + +void fetchScriptLimitsRegionInfoResponder::error(U32 status, const std::string& reason) +{ + llinfos << "Error from responder " << reason << llendl; +} + +void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content) +{ + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); + if(!instance) + { + llinfos << "Failed to get llfloaterscriptlimits instance" << llendl; + } + else + { + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + panel_memory->setRegionSummary(content); + LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); + panel_urls->setRegionSummary(content); + } +} + +void fetchScriptLimitsRegionSummaryResponder::error(U32 status, const std::string& reason) +{ + llinfos << "Error from responder " << reason << llendl; +} + +void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content) +{ + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); + + if(!instance) + { + llinfos << "Failed to get llfloaterscriptlimits instance" << llendl; + } + else + { + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + panel_memory->setRegionDetails(content); + + LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); + panel_urls->setRegionDetails(content); + } +} + +void fetchScriptLimitsRegionDetailsResponder::error(U32 status, const std::string& reason) +{ + llinfos << "Error from responder " << reason << llendl; +} + +void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content) +{ + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); + + if(!instance) + { + llinfos << "Failed to get llfloaterscriptlimits instance" << llendl; + } + else + { + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsAttachment* panel = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel"); + panel->setAttachmentDetails(content); + } +} + +void fetchScriptLimitsAttachmentInfoResponder::error(U32 status, const std::string& reason) +{ + llinfos << "Error from responder " << reason << llendl; +} + +///---------------------------------------------------------------------------- +// Memory Panel +///---------------------------------------------------------------------------- + +BOOL LLPanelScriptLimitsRegionMemory::getLandScriptResources() +{ + LLSD body; + std::string url = gAgent.getRegion()->getCapability("LandResources"); + if (!url.empty()) + { + body["parcel_id"] = mParcelId; + + LLSD info; + info["parcel_id"] = mParcelId; + LLHTTPClient::post(url, body, new fetchScriptLimitsRegionInfoResponder(info)); + + return TRUE; + } + else + { + return FALSE; + } +} + +void LLPanelScriptLimitsRegionMemory::processParcelInfo(const LLParcelData& parcel_data) +{ + mParcelId = parcel_data.parcel_id; + + if(!getLandScriptResources()) + { + std::string msg_error = LLTrans::getString("ScriptLimitsRequestError"); + childSetValue("loading_text", LLSD(msg_error)); + } + else + { + std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting"); + childSetValue("loading_text", LLSD(msg_waiting)); + } +} + +void LLPanelScriptLimitsRegionMemory::setParcelID(const LLUUID& parcel_id) +{ + if (!parcel_id.isNull()) + { + LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this); + LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id); + } + else + { + std::string msg_error = LLTrans::getString("ScriptLimitsRequestError"); + childSetValue("loading_text", LLSD(msg_error)); + } +} + +// virtual +void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::string& reason) +{ + llerrs << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl; +} + +void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) +{ + LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list"); + + S32 number_parcels = content["parcels"].size(); + + LLStringUtil::format_map_t args_parcels; + args_parcels["[PARCELS]"] = llformat ("%d", number_parcels); + std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels); + childSetValue("parcels_listed", LLSD(msg_parcels)); + + S32 total_objects = 0; + S32 total_size = 0; + + for(S32 i = 0; i < number_parcels; i++) + { + std::string parcel_name = content["parcels"][i]["name"].asString(); + + S32 number_objects = content["parcels"][i]["objects"].size(); + for(S32 j = 0; j < number_objects; j++) + { + S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / 1024; + total_size += size; + + std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString(); + LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID(); + + LLSD element; + + element["id"] = task_id; + element["columns"][0]["column"] = "size"; + element["columns"][0]["value"] = llformat("%d", size); + element["columns"][0]["font"] = "SANSSERIF"; + element["columns"][1]["column"] = "name"; + element["columns"][1]["value"] = name_buf; + element["columns"][1]["font"] = "SANSSERIF"; + element["columns"][2]["column"] = "owner"; + element["columns"][2]["value"] = ""; + element["columns"][2]["font"] = "SANSSERIF"; + element["columns"][3]["column"] = "location"; + element["columns"][3]["value"] = parcel_name; + element["columns"][3]["font"] = "SANSSERIF"; + + list->addElement(element); + mObjectListIDs.push_back(task_id); + total_objects++; + } + } + + mParcelMemoryUsed =total_size; + mGotParcelMemoryUsed = TRUE; + populateParcelMemoryText(); +} + +void LLPanelScriptLimitsRegionMemory::populateParcelMemoryText() +{ + if(mGotParcelMemoryUsed && mGotParcelMemoryMax) + { +#ifdef USE_SIMPLE_SUMMARY + LLStringUtil::format_map_t args_parcel_memory; + args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed); + std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsedSimple", args_parcel_memory); + childSetValue("memory_used", LLSD(msg_parcel_memory)); +#else + S32 parcel_memory_available = mParcelMemoryMax - mParcelMemoryUsed; + + LLStringUtil::format_map_t args_parcel_memory; + args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed); + args_parcel_memory["[MAX]"] = llformat ("%d", mParcelMemoryMax); + args_parcel_memory["[AVAILABLE]"] = llformat ("%d", parcel_memory_available); + std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_parcel_memory); + childSetValue("memory_used", LLSD(msg_parcel_memory)); +#endif + + childSetValue("loading_text", LLSD(std::string(""))); + } +} + +void LLPanelScriptLimitsRegionMemory::setRegionSummary(LLSD content) +{ + if(content["summary"]["available"][0]["type"].asString() == std::string("memory")) + { + mParcelMemoryMax = content["summary"]["available"][0]["amount"].asInteger(); + mGotParcelMemoryMax = TRUE; + } + else if(content["summary"]["available"][1]["type"].asString() == std::string("memory")) + { + mParcelMemoryMax = content["summary"]["available"][1]["amount"].asInteger(); + mGotParcelMemoryMax = TRUE; + } + else + { + llinfos << "summary doesn't contain memory info" << llendl; + return; + } +/* + currently this is broken on the server, so we get this value from the details section + and update via populateParcelMemoryText() when both sets of information have been returned + + when the sim is fixed this should be used instead: + if(content["summary"]["used"][0]["type"].asString() == std::string("memory")) + { + mParcelMemoryUsed = content["summary"]["used"][0]["amount"].asInteger(); + mGotParcelMemoryUsed = TRUE; + } + else if(content["summary"]["used"][1]["type"].asString() == std::string("memory")) + { + mParcelMemoryUsed = content["summary"]["used"][1]["amount"].asInteger(); + mGotParcelMemoryUsed = TRUE; + } + else + { + //ERROR!!! + return; + }*/ + + populateParcelMemoryText(); +} + +BOOL LLPanelScriptLimitsRegionMemory::postBuild() +{ + childSetAction("refresh_list_btn", onClickRefresh, this); + childSetAction("highlight_btn", onClickHighlight, this); + childSetAction("return_btn", onClickReturn, this); + + std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting"); + childSetValue("loading_text", LLSD(msg_waiting)); + + return StartRequestChain(); +} + +BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain() +{ + LLUUID region_id; + + LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land"); + if(!instance) + { + //this isnt really an error... +// llinfos << "Failed to get about land instance" << llendl; +// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); + childSetValue("loading_text", LLSD(std::string(""))); + //might have to do parent post build here + //if not logic below could use early outs + return FALSE; + } + + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); + + LLParcel* parcel = instance->getCurrentSelectedParcel(); + LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + + LLUUID current_region_id = gAgent.getRegion()->getRegionID(); + + if ((region) && (parcel)) + { + LLVector3 parcel_center = parcel->getCenterpoint(); + + region_id = region->getRegionID(); + + if(region_id != current_region_id) + { + std::string msg_wrong_region = LLTrans::getString("ScriptLimitsRequestWrongRegion"); + childSetValue("loading_text", LLSD(msg_wrong_region)); + panel_urls->childSetValue("loading_text", LLSD(msg_wrong_region)); + return FALSE; + } + + LLVector3d pos_global = region->getCenterGlobal(); + + LLSD body; + std::string url = region->getCapability("RemoteParcelRequest"); + if (!url.empty()) + { + body["location"] = ll_sd_from_vector3(parcel_center); + if (!region_id.isNull()) + { + body["region_id"] = region_id; + } + if (!pos_global.isExactlyZero()) + { + U64 region_handle = to_region_handle(pos_global); + body["region_handle"] = ll_sd_from_U64(region_handle); + } + LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle())); + } + else + { + llwarns << "Can't get parcel info for script information request" << region_id + << ". Region: " << region->getName() + << " does not support RemoteParcelRequest" << llendl; + + std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); + childSetValue("loading_text", LLSD(msg_waiting)); + panel_urls->childSetValue("loading_text", LLSD(msg_waiting)); + } + } + else + { + std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); + childSetValue("loading_text", LLSD(msg_waiting)); + panel_urls->childSetValue("loading_text", LLSD(msg_waiting)); + } + + return LLPanelScriptLimitsInfo::postBuild(); +} + +void LLPanelScriptLimitsRegionMemory::clearList() +{ + LLCtrlListInterface *list = childGetListInterface("scripts_list"); + + if (list) + { + list->operateOnAll(LLCtrlListInterface::OP_DELETE); + } + + mGotParcelMemoryUsed = FALSE; + mGotParcelMemoryMax = FALSE; + + LLStringUtil::format_map_t args_parcel_memory; + std::string msg_empty_string(""); + childSetValue("memory_used", LLSD(msg_empty_string)); + childSetValue("parcels_listed", LLSD(msg_empty_string)); + + mObjectListIDs.clear(); +} + +// static +void LLPanelScriptLimitsRegionMemory::onClickRefresh(void* userdata) +{ + llinfos << "LLPanelRegionGeneralInfo::onClickRefresh" << llendl; + + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); + if(instance) + { + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + panel_memory->clearList(); + + LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); + panel_urls->clearList(); + + panel_memory->StartRequestChain(); + return; + } + else + { + llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl; + return; + } +} + +void LLPanelScriptLimitsRegionMemory::showBeacon() +{ +/* LLScrollListCtrl* list = getChild<LLScrollListCtrl>("scripts_list"); + if (!list) return; + + LLScrollListItem* first_selected = list->getFirstSelected(); + if (!first_selected) return; + + std::string name = first_selected->getColumn(1)->getValue().asString(); + std::string pos_string = first_selected->getColumn(3)->getValue().asString(); + + llinfos << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" <<llendl; + llinfos << "name = " << name << " pos = " << pos_string << llendl; + + F32 x, y, z; + S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z); + if (matched != 3) return; + + LLVector3 pos_agent(x, y, z); + LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); + llinfos << "name = " << name << " pos = " << pos_string << llendl; + std::string tooltip(""); + LLTracker::trackLocation(pos_global, name, tooltip, LLTracker::LOCATION_ITEM);*/ +} + +// static +void LLPanelScriptLimitsRegionMemory::onClickHighlight(void* userdata) +{ +/* llinfos << "LLPanelRegionGeneralInfo::onClickHighlight" << llendl; + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); + if(instance) + { + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + panel->showBeacon(); + return; + } + else + { + llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl; +// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); +// panel->childSetValue("loading_text", LLSD(msg_waiting)); + return; + }*/ +} + +void LLPanelScriptLimitsRegionMemory::returnObjects() +{ +/* llinfos << "started" << llendl; + LLMessageSystem *msg = gMessageSystem; + + LLViewerRegion* region = gAgent.getRegion(); + if (!region) return; + + llinfos << "got region" << llendl; + LLCtrlListInterface *list = childGetListInterface("scripts_list"); + if (!list || list->getItemCount() == 0) return; + + llinfos << "got list" << llendl; + std::vector<LLUUID>::iterator id_itor; + + bool start_message = true; + + for (id_itor = mObjectListIDs.begin(); id_itor != mObjectListIDs.end(); ++id_itor) + { + LLUUID task_id = *id_itor; + llinfos << task_id << llendl; + if (!list->isSelected(task_id)) + { + llinfos << "not selected" << llendl; + // Selected only + continue; + } + llinfos << "selected" << llendl; + if (start_message) + { + msg->newMessageFast(_PREHASH_ParcelReturnObjects); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ParcelData); + msg->addS32Fast(_PREHASH_LocalID, -1); // Whole region + msg->addS32Fast(_PREHASH_ReturnType, RT_LIST); + start_message = false; + llinfos << "start message" << llendl; + } + + msg->nextBlockFast(_PREHASH_TaskIDs); + msg->addUUIDFast(_PREHASH_TaskID, task_id); + llinfos << "added id" << llendl; + + if (msg->isSendFullFast(_PREHASH_TaskIDs)) + { + msg->sendReliable(region->getHost()); + start_message = true; + llinfos << "sent 1" << llendl; + } + } + + if (!start_message) + { + msg->sendReliable(region->getHost()); + llinfos << "sent 2" << llendl; + }*/ +} + +// static +void LLPanelScriptLimitsRegionMemory::onClickReturn(void* userdata) +{ +/* llinfos << "LLPanelRegionGeneralInfo::onClickReturn" << llendl; + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); + if(instance) + { + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + panel->returnObjects(); + return; + } + else + { + llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl; +// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); +// panel->childSetValue("loading_text", LLSD(msg_waiting)); + return; + }*/ +} + +///---------------------------------------------------------------------------- +// URLs Panel +///---------------------------------------------------------------------------- + +void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content) +{ + LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list"); + + S32 number_parcels = content["parcels"].size(); + + LLStringUtil::format_map_t args_parcels; + args_parcels["[PARCELS]"] = llformat ("%d", number_parcels); + std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels); + childSetValue("parcels_listed", LLSD(msg_parcels)); + + S32 total_objects = 0; + S32 total_size = 0; + + for(S32 i = 0; i < number_parcels; i++) + { + std::string parcel_name = content["parcels"][i]["name"].asString(); + llinfos << parcel_name << llendl; + + S32 number_objects = content["parcels"][i]["objects"].size(); + for(S32 j = 0; j < number_objects; j++) + { + if(content["parcels"][i]["objects"][j]["resources"].has("urls")) + { + S32 size = content["parcels"][i]["objects"][j]["resources"]["urls"].asInteger(); + total_size += size; + + std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString(); + LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID(); + + LLSD element; + + element["id"] = task_id; + element["columns"][0]["column"] = "urls"; + element["columns"][0]["value"] = llformat("%d", size); + element["columns"][0]["font"] = "SANSSERIF"; + element["columns"][1]["column"] = "name"; + element["columns"][1]["value"] = name_buf; + element["columns"][1]["font"] = "SANSSERIF"; + element["columns"][2]["column"] = "owner"; + element["columns"][2]["value"] = ""; + element["columns"][2]["font"] = "SANSSERIF"; + element["columns"][3]["column"] = "location"; + element["columns"][3]["value"] = parcel_name; + element["columns"][3]["font"] = "SANSSERIF"; + + list->addElement(element); + mObjectListIDs.push_back(task_id); + total_objects++; + } + } + } + + mParcelURLsUsed =total_size; + mGotParcelURLsUsed = TRUE; + populateParcelURLsText(); +} + +void LLPanelScriptLimitsRegionURLs::populateParcelURLsText() +{ + if(mGotParcelURLsUsed && mGotParcelURLsMax) + { + +#ifdef USE_SIMPLE_SUMMARY + LLStringUtil::format_map_t args_parcel_urls; + args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed); + std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsedSimple", args_parcel_urls); + childSetValue("urls_used", LLSD(msg_parcel_urls)); +#else + S32 parcel_urls_available = mParcelURLsMax - mParcelURLsUsed; + + LLStringUtil::format_map_t args_parcel_urls; + args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed); + args_parcel_urls["[MAX]"] = llformat ("%d", mParcelURLsMax); + args_parcel_urls["[AVAILABLE]"] = llformat ("%d", parcel_urls_available); + std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_parcel_urls); + childSetValue("urls_used", LLSD(msg_parcel_urls)); +#endif + + childSetValue("loading_text", LLSD(std::string(""))); + + } +} + +void LLPanelScriptLimitsRegionURLs::setRegionSummary(LLSD content) +{ + if(content["summary"]["available"][0]["type"].asString() == std::string("urls")) + { + mParcelURLsMax = content["summary"]["available"][0]["amount"].asInteger(); + mGotParcelURLsMax = TRUE; + } + else if(content["summary"]["available"][1]["type"].asString() == std::string("urls")) + { + mParcelURLsMax = content["summary"]["available"][1]["amount"].asInteger(); + mGotParcelURLsMax = TRUE; + } + else + { + llinfos << "summary contains no url info" << llendl; + return; + } +/* + currently this is broken on the server, so we get this value from the details section + and update via populateParcelMemoryText() when both sets of information have been returned + + when the sim is fixed this should be used instead: + if(content["summary"]["used"][0]["type"].asString() == std::string("urls")) + { + mParcelURLsUsed = content["summary"]["used"][0]["amount"].asInteger(); + mGotParcelURLsUsed = TRUE; + } + else if(content["summary"]["used"][1]["type"].asString() == std::string("urls")) + { + mParcelURLsUsed = content["summary"]["used"][1]["amount"].asInteger(); + mGotParcelURLsUsed = TRUE; + } + else + { + //ERROR!!! + return; + }*/ + + populateParcelURLsText(); +} + +BOOL LLPanelScriptLimitsRegionURLs::postBuild() +{ + childSetAction("refresh_list_btn", onClickRefresh, this); + childSetAction("highlight_btn", onClickHighlight, this); + childSetAction("return_btn", onClickReturn, this); + + std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting"); + childSetValue("loading_text", LLSD(msg_waiting)); + return FALSE; +} + +void LLPanelScriptLimitsRegionURLs::clearList() +{ + LLCtrlListInterface *list = childGetListInterface("scripts_list"); + + if (list) + { + list->operateOnAll(LLCtrlListInterface::OP_DELETE); + } + + mGotParcelURLsUsed = FALSE; + mGotParcelURLsMax = FALSE; + + LLStringUtil::format_map_t args_parcel_urls; + std::string msg_empty_string(""); + childSetValue("urls_used", LLSD(msg_empty_string)); + childSetValue("parcels_listed", LLSD(msg_empty_string)); + + mObjectListIDs.clear(); +} + +// static +void LLPanelScriptLimitsRegionURLs::onClickRefresh(void* userdata) +{ + llinfos << "Refresh clicked" << llendl; + + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); + if(instance) + { + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + // use the memory panel to re-request all the info + panel_memory->clearList(); + + LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel"); + // but the urls panel to clear itself + panel_urls->clearList(); + + panel_memory->StartRequestChain(); + return; + } + else + { + llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl; + return; + } +} + +// static +void LLPanelScriptLimitsRegionURLs::onClickHighlight(void* userdata) +{ +/* llinfos << "Highlight clicked" << llendl; + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); + if(instance) + { + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + // use the beacon function from the memory panel + panel->showBeacon(); + return; + } + else + { + llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl; +// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); +// panel->childSetValue("loading_text", LLSD(msg_waiting)); + return; + }*/ +} + +// static +void LLPanelScriptLimitsRegionURLs::onClickReturn(void* userdata) +{ +/* llinfos << "Return clicked" << llendl; + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); + if(instance) + { + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel"); + // use the return function from the memory panel + panel->returnObjects(); + return; + } + else + { + llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl; +// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError"); +// panel->childSetValue("loading_text", LLSD(msg_waiting)); + return; + }*/ +} + +///---------------------------------------------------------------------------- +// Attachment Panel +///---------------------------------------------------------------------------- + +BOOL LLPanelScriptLimitsAttachment::requestAttachmentDetails() +{ + LLSD body; + std::string url = gAgent.getRegion()->getCapability("AttachmentResources"); + if (!url.empty()) + { + LLHTTPClient::get(url, body, new fetchScriptLimitsAttachmentInfoResponder()); + return TRUE; + } + else + { + return FALSE; + } +} + +void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content) +{ + LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list"); + S32 number_attachments = content["attachments"].size(); + + for(int i = 0; i < number_attachments; i++) + { + std::string humanReadableLocation = ""; + if(content["attachments"][i].has("location")) + { + std::string actualLocation = content["attachments"][i]["location"]; + humanReadableLocation = LLTrans::getString(actualLocation.c_str()); + } + + S32 number_objects = content["attachments"][i]["objects"].size(); + for(int j = 0; j < number_objects; j++) + { + LLUUID task_id = content["attachments"][i]["objects"][j]["id"].asUUID(); + S32 size = 0; + if(content["attachments"][i]["objects"][j]["resources"].has("memory")) + { + size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger(); + } + S32 urls = 0; + if(content["attachments"][i]["objects"][j]["resources"].has("urls")) + { + urls = content["attachments"][i]["objects"][j]["resources"]["urls"].asInteger(); + } + std::string name = content["attachments"][i]["objects"][j]["name"].asString(); + + LLSD element; + + element["id"] = task_id; + element["columns"][0]["column"] = "size"; + element["columns"][0]["value"] = llformat("%d", size); + element["columns"][0]["font"] = "SANSSERIF"; + + element["columns"][1]["column"] = "urls"; + element["columns"][1]["value"] = llformat("%d", urls); + element["columns"][1]["font"] = "SANSSERIF"; + + element["columns"][2]["column"] = "name"; + element["columns"][2]["value"] = name; + element["columns"][2]["font"] = "SANSSERIF"; + + element["columns"][3]["column"] = "location"; + element["columns"][3]["value"] = humanReadableLocation; + element["columns"][3]["font"] = "SANSSERIF"; + + list->addElement(element); + } + } + + childSetValue("loading_text", LLSD(std::string(""))); +} + +BOOL LLPanelScriptLimitsAttachment::postBuild() +{ + childSetAction("refresh_list_btn", onClickRefresh, this); + + std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting"); + childSetValue("loading_text", LLSD(msg_waiting)); + return requestAttachmentDetails(); +} + +void LLPanelScriptLimitsAttachment::clearList() +{ + LLCtrlListInterface *list = childGetListInterface("scripts_list"); + + if (list) + { + list->operateOnAll(LLCtrlListInterface::OP_DELETE); + } + + std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting"); + childSetValue("loading_text", LLSD(msg_waiting)); +} + +// static +void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata) +{ + llinfos << "Refresh clicked" << llendl; + + LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits"); + if(instance) + { + LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels"); + LLPanelScriptLimitsAttachment* panel_attachments = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel"); + panel_attachments->clearList(); + panel_attachments->requestAttachmentDetails(); + return; + } + else + { + llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl; + return; + } +} diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h new file mode 100644 index 0000000000..88239136e3 --- /dev/null +++ b/indra/newview/llfloaterscriptlimits.h @@ -0,0 +1,259 @@ +/** + * @file llfloaterscriptlimits.h + * @author Gabriel Lee + * @brief Declaration of the region info and controls floater and panels. + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERSCRIPTLIMITS_H +#define LL_LLFLOATERSCRIPTLIMITS_H + +#include <vector> +#include "llfloater.h" +#include "llhost.h" +#include "llpanel.h" +#include "llremoteparcelrequest.h" + +class LLPanelScriptLimitsInfo; +class LLTabContainer; + +class LLPanelScriptLimitsRegionMemory; + +class LLFloaterScriptLimits : public LLFloater +{ + friend class LLFloaterReg; +public: + + /*virtual*/ BOOL postBuild(); + + // from LLPanel + virtual void refresh(); + +private: + + LLFloaterScriptLimits(const LLSD& seed); + ~LLFloaterScriptLimits(); + +protected: + + LLTabContainer* mTab; + typedef std::vector<LLPanelScriptLimitsInfo*> info_panels_t; + info_panels_t mInfoPanels; +}; + + +// Base class for all script limits information panels. +class LLPanelScriptLimitsInfo : public LLPanel +{ +public: + LLPanelScriptLimitsInfo(); + + virtual BOOL postBuild(); + virtual void updateChild(LLUICtrl* child_ctrl); + +protected: + void initCtrl(const std::string& name); + + typedef std::vector<std::string> strings_t; + + LLHost mHost; +}; + +///////////////////////////////////////////////////////////////////////////// +// Responders +///////////////////////////////////////////////////////////////////////////// + +class fetchScriptLimitsRegionInfoResponder: public LLHTTPClient::Responder +{ + public: + fetchScriptLimitsRegionInfoResponder(const LLSD& info) : mInfo(info) {}; + + void result(const LLSD& content); + void error(U32 status, const std::string& reason); + public: + protected: + LLSD mInfo; +}; + +class fetchScriptLimitsRegionSummaryResponder: public LLHTTPClient::Responder +{ + public: + fetchScriptLimitsRegionSummaryResponder(const LLSD& info) : mInfo(info) {}; + + void result(const LLSD& content); + void error(U32 status, const std::string& reason); + public: + protected: + LLSD mInfo; +}; + +class fetchScriptLimitsRegionDetailsResponder: public LLHTTPClient::Responder +{ + public: + fetchScriptLimitsRegionDetailsResponder(const LLSD& info) : mInfo(info) {}; + + void result(const LLSD& content); + void error(U32 status, const std::string& reason); + public: + protected: + LLSD mInfo; +}; + +class fetchScriptLimitsAttachmentInfoResponder: public LLHTTPClient::Responder +{ + public: + fetchScriptLimitsAttachmentInfoResponder() {}; + + void result(const LLSD& content); + void error(U32 status, const std::string& reason); + public: + protected: +}; + +///////////////////////////////////////////////////////////////////////////// +// Memory panel +///////////////////////////////////////////////////////////////////////////// + +class LLPanelScriptLimitsRegionMemory : public LLPanelScriptLimitsInfo, LLRemoteParcelInfoObserver +{ + +public: + LLPanelScriptLimitsRegionMemory() + : LLPanelScriptLimitsInfo(), LLRemoteParcelInfoObserver(), mParcelId(LLUUID()), mGotParcelMemoryUsed(FALSE), mGotParcelMemoryMax(FALSE) {}; + ~LLPanelScriptLimitsRegionMemory() + { + LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this); + }; + + // LLPanel + virtual BOOL postBuild(); + + void setRegionDetails(LLSD content); + void setRegionSummary(LLSD content); + + BOOL StartRequestChain(); + + void populateParcelMemoryText(); + BOOL getLandScriptResources(); + void clearList(); + void showBeacon(); + void returnObjects(); + +private: + + LLUUID mParcelId; + BOOL mGotParcelMemoryUsed; + BOOL mGotParcelMemoryMax; + S32 mParcelMemoryMax; + S32 mParcelMemoryUsed; + + std::vector<LLUUID> mObjectListIDs; + +protected: + +// LLRemoteParcelInfoObserver interface: +/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); +/*virtual*/ void setParcelID(const LLUUID& parcel_id); +/*virtual*/ void setErrorStatus(U32 status, const std::string& reason); + + static void onClickRefresh(void* userdata); + static void onClickHighlight(void* userdata); + static void onClickReturn(void* userdata); +}; + +///////////////////////////////////////////////////////////////////////////// +// URLs panel +///////////////////////////////////////////////////////////////////////////// + +class LLPanelScriptLimitsRegionURLs : public LLPanelScriptLimitsInfo +{ + +public: + LLPanelScriptLimitsRegionURLs() + : LLPanelScriptLimitsInfo(), mParcelId(LLUUID()), mGotParcelURLsUsed(FALSE), mGotParcelURLsMax(FALSE) {}; + ~LLPanelScriptLimitsRegionURLs() + { + }; + + // LLPanel + virtual BOOL postBuild(); + + void setRegionDetails(LLSD content); + void setRegionSummary(LLSD content); + + void populateParcelURLsText(); + void clearList(); + +private: + + LLUUID mParcelId; + BOOL mGotParcelURLsUsed; + BOOL mGotParcelURLsMax; + S32 mParcelURLsMax; + S32 mParcelURLsUsed; + + std::vector<LLUUID> mObjectListIDs; + +protected: + + static void onClickRefresh(void* userdata); + static void onClickHighlight(void* userdata); + static void onClickReturn(void* userdata); +}; + +///////////////////////////////////////////////////////////////////////////// +// Attachment panel +///////////////////////////////////////////////////////////////////////////// + +class LLPanelScriptLimitsAttachment : public LLPanelScriptLimitsInfo +{ + +public: + LLPanelScriptLimitsAttachment() + : LLPanelScriptLimitsInfo() {}; + ~LLPanelScriptLimitsAttachment() + { + }; + + // LLPanel + virtual BOOL postBuild(); + + void setAttachmentDetails(LLSD content); + + BOOL requestAttachmentDetails(); + void clearList(); + +private: + +protected: + + static void onClickRefresh(void* userdata); +}; + +#endif diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 595d84f9f0..c6d9fee630 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -77,6 +77,15 @@ void LLFloaterSearch::onOpen(const LLSD& key) search(key); } +void LLFloaterSearch::onClose(bool app_quitting) +{ + if (! app_quitting) + { + // Show the blank home page ready for the next onOpen() + mBrowser->navigateHome(); + } +} + void LLFloaterSearch::handleMediaEvent(LLPluginClassMedia *self, EMediaEvent event) { switch (event) @@ -110,6 +119,11 @@ void LLFloaterSearch::search(const LLSD &key) return; } + // display the blank home page first, to clear the display of + // any previous search results while the new results load. + // The home page is set in floater_search.xml as start_url. + mBrowser->navigateHome(); + // reset the god level warning as we're sending the latest state childHide("refresh_search"); mSearchGodLevel = gAgent.getGodLevel(); diff --git a/indra/newview/llfloatersearch.h b/indra/newview/llfloatersearch.h index ba817adf7f..0a8d9bbe36 100644 --- a/indra/newview/llfloatersearch.h +++ b/indra/newview/llfloatersearch.h @@ -59,6 +59,8 @@ public: /// see search() for details on the key parameter. /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_quitting); + /// perform a search with the specific search term. /// The key should be a map that can contain the following keys: /// - "id": specifies the text phrase to search for diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index e5260aa7b9..e2b0c4b66f 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -89,14 +89,14 @@ private: void setBadge(const char* id, Badge badge); static void onChangeValue(LLUICtrl *ctrl, void *userdata); - static void doSelectAgent(void *userdata); + void doSelectAgent(); static void doCancel(void *userdata); static void doSellLand(void *userdata); bool onConfirmSale(const LLSD& notification, const LLSD& response); static void doShowObjects(void *userdata); static bool callbackHighlightTransferable(const LLSD& notification, const LLSD& response); - static void callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data); + void callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids); public: virtual BOOL postBuild(); @@ -165,7 +165,7 @@ BOOL LLFloaterSellLandUI::postBuild() childSetCommitCallback("price", onChangeValue, this); childSetPrevalidate("price", LLLineEditor::prevalidateNonNegativeS32); childSetCommitCallback("sell_objects", onChangeValue, this); - childSetAction("sell_to_select_agent", doSelectAgent, this); + childSetAction("sell_to_select_agent", boost::bind( &LLFloaterSellLandUI::doSelectAgent, this)); childSetAction("cancel_btn", doCancel, this); childSetAction("sell_btn", doSellLand, this); childSetAction("show_objects", doShowObjects, this); @@ -361,7 +361,7 @@ void LLFloaterSellLandUI::onChangeValue(LLUICtrl *ctrl, void *userdata) self->mSellToBuyer = true; if (self->mAuthorizedBuyer.isNull()) { - doSelectAgent(self); + self->doSelectAgent(); } } else if (sell_to == "anyone") @@ -384,30 +384,26 @@ void LLFloaterSellLandUI::onChangeValue(LLUICtrl *ctrl, void *userdata) self->refreshUI(); } -// static -void LLFloaterSellLandUI::doSelectAgent(void *userdata) +void LLFloaterSellLandUI::doSelectAgent() { - LLFloaterSellLandUI* floaterp = (LLFloaterSellLandUI*)userdata; // grandparent is a floater, in order to set up dependency - floaterp->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarPick, floaterp, FALSE, TRUE)); + addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE)); } -// static -void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data) +void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids) { - LLFloaterSellLandUI* floaterp = (LLFloaterSellLandUI*)data; - LLParcel* parcel = floaterp->mParcelSelection->getParcel(); + LLParcel* parcel = mParcelSelection->getParcel(); if (names.empty() || ids.empty()) return; LLUUID id = ids[0]; parcel->setAuthorizedBuyerID(id); - floaterp->mAuthorizedBuyer = ids[0]; + mAuthorizedBuyer = ids[0]; - floaterp->childSetText("sell_to_agent", names[0]); + childSetText("sell_to_agent", names[0]); - floaterp->refreshUI(); + refreshUI(); } // static diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index dbecd45d1f..f53b62e490 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1379,7 +1379,6 @@ void LLFloaterSnapshot::Impl::onClickDiscard(void* data) if (view) { - view->getParent()->setMouseOpaque(FALSE); view->closeFloater(); } } @@ -2105,6 +2104,12 @@ void LLFloaterSnapshot::onOpen(const LLSD& key) gSnapshotFloaterView->adjustToFitScreen(this, FALSE); } +void LLFloaterSnapshot::onClose(bool app_quitting) +{ + getParent()->setMouseOpaque(FALSE); +} + + //static void LLFloaterSnapshot::update() { diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index bd01f6c573..1333497bd2 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -52,6 +52,7 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_quitting); static void update(); diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index 86992d6a31..c930e99bad 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -162,7 +162,7 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data) msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ReportType, mCurrentMode); LLScrollListCtrl *list = getChild<LLScrollListCtrl>("objects_list"); - + S32 block_count = msg->getNumberOfBlocks("ReportData"); for (S32 block = 0; block < block_count; ++block) { @@ -432,7 +432,6 @@ void LLFloaterTopObjects::onRefresh() filter = mFilter; clearList(); - LLMessageSystem *msg = gMessageSystem; msg->newMessageFast(_PREHASH_LandStatRequest); msg->nextBlockFast(_PREHASH_AgentData); @@ -465,7 +464,7 @@ void LLFloaterTopObjects::onGetByOwnerName() } void LLFloaterTopObjects::showBeacon() -{ +{ LLScrollListCtrl* list = getChild<LLScrollListCtrl>("objects_list"); if (!list) return; diff --git a/indra/newview/llfloaterwindowsize.cpp b/indra/newview/llfloaterwindowsize.cpp new file mode 100644 index 0000000000..5519be6f08 --- /dev/null +++ b/indra/newview/llfloaterwindowsize.cpp @@ -0,0 +1,164 @@ +/** + * @file llfloaterwindowsize.cpp + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterwindowsize.h" + +// Viewer includes +#include "llviewerwindow.h" + +// Linden library includes +#include "llcombobox.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "lluictrl.h" + +// System libraries +#include <boost/regex.hpp> + +// Extract from strings of the form "<width> x <height>", e.g. "640 x 480". +bool extractWindowSizeFromString(const std::string& instr, U32 *width, U32 *height) +{ + boost::cmatch what; + // matches (any number)(any non-number)(any number) + const boost::regex expression("([0-9]+)[^0-9]+([0-9]+)"); + if (boost::regex_match(instr.c_str(), what, expression)) + { + *width = atoi(what[1].first); + *height = atoi(what[2].first); + return true; + } + + *width = 0; + *height = 0; + return false; +} + + +///---------------------------------------------------------------------------- +/// Class LLFloaterWindowSize +///---------------------------------------------------------------------------- +class LLFloaterWindowSize +: public LLFloater +{ + friend class LLFloaterReg; +private: + LLFloaterWindowSize(const LLSD& key); + virtual ~LLFloaterWindowSize(); + +public: + /*virtual*/ BOOL postBuild(); + void initWindowSizeControls(); + void onClickSet(); + void onClickCancel(); +}; + + +LLFloaterWindowSize::LLFloaterWindowSize(const LLSD& key) +: LLFloater(key) +{ + //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_window_size.xml"); +} + +LLFloaterWindowSize::~LLFloaterWindowSize() +{ +} + +BOOL LLFloaterWindowSize::postBuild() +{ + center(); + initWindowSizeControls(); + getChild<LLUICtrl>("set_btn")->setCommitCallback( + boost::bind(&LLFloaterWindowSize::onClickSet, this)); + getChild<LLUICtrl>("cancel_btn")->setCommitCallback( + boost::bind(&LLFloaterWindowSize::onClickCancel, this)); + setDefaultBtn("set_btn"); + return TRUE; +} + +void LLFloaterWindowSize::initWindowSizeControls() +{ + LLComboBox* ctrl_window_size = getChild<LLComboBox>("window_size_combo"); + + // Look to see if current window size matches existing window sizes, if so then + // just set the selection value... + const U32 height = gViewerWindow->getWindowHeightRaw(); + const U32 width = gViewerWindow->getWindowWidthRaw(); + for (S32 i=0; i < ctrl_window_size->getItemCount(); i++) + { + U32 height_test = 0; + U32 width_test = 0; + ctrl_window_size->setCurrentByIndex(i); + std::string resolution = ctrl_window_size->getValue().asString(); + if (extractWindowSizeFromString(resolution, &width_test, &height_test)) + { + if ((height_test == height) && (width_test == width)) + { + return; + } + } + } + // ...otherwise, add a new entry with the current window height/width. + LLUIString resolution_label = getString("resolution_format"); + resolution_label.setArg("[RES_X]", llformat("%d", width)); + resolution_label.setArg("[RES_Y]", llformat("%d", height)); + ctrl_window_size->add(resolution_label, ADD_TOP); + ctrl_window_size->setCurrentByIndex(0); +} + +void LLFloaterWindowSize::onClickSet() +{ + LLComboBox* ctrl_window_size = getChild<LLComboBox>("window_size_combo"); + U32 width = 0; + U32 height = 0; + std::string resolution = ctrl_window_size->getValue().asString(); + if (extractWindowSizeFromString(resolution, &width, &height)) + { + LLViewerWindow::movieSize(width, height); + } + closeFloater(); +} + +void LLFloaterWindowSize::onClickCancel() +{ + closeFloater(); +} + +///---------------------------------------------------------------------------- +/// LLFloaterWindowSizeUtil +///---------------------------------------------------------------------------- +void LLFloaterWindowSizeUtil::registerFloater() +{ + LLFloaterReg::add("window_size", "floater_window_size.xml", + &LLFloaterReg::build<LLFloaterWindowSize>); + +} diff --git a/indra/newview/llfloaterwindowsize.h b/indra/newview/llfloaterwindowsize.h new file mode 100644 index 0000000000..fd9d17323a --- /dev/null +++ b/indra/newview/llfloaterwindowsize.h @@ -0,0 +1,41 @@ +/** + * @file llfloaterwindowsize.h + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LLFLOATERWINDOWSIZE_H +#define LLFLOATERWINDOWSIZE_H + +// Allow user to set the window size for filming tutorials, machinima, etc +namespace LLFloaterWindowSizeUtil +{ + void registerFloater(); +} + +#endif diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 8b05f8614d..112b23d2df 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -206,7 +206,8 @@ LLFolderView::LLFolderView(const Params& p) mAutoOpenCandidate = NULL; mAutoOpenTimer.stop(); mKeyboardSelection = FALSE; - mIndentation = -LEFT_INDENTATION; // children start at indentation 0 + static LLUICachedControl<S32> indentation("FolderIndentation", 0); + mIndentation = -indentation; // children start at indentation 0 gIdleCallbacks.addFunction(idle, this); //clear label @@ -751,7 +752,7 @@ void LLFolderView::sanitizeSelection() } // Don't allow invisible items (such as root folders) to be selected. - if (item->getDontShowInHierarchy()) + if (item->getHidden()) { items_to_remove.push_back(item); } @@ -774,7 +775,7 @@ void LLFolderView::sanitizeSelection() parent_folder; parent_folder = parent_folder->getParentFolder()) { - if (parent_folder->potentiallyVisible() && !parent_folder->getDontShowInHierarchy()) + if (parent_folder->potentiallyVisible() && !parent_folder->getHidden()) { // give initial selection to first ancestor folder that potentially passes the filter if (!new_selection) @@ -796,7 +797,7 @@ void LLFolderView::sanitizeSelection() // nothing selected to start with, so pick "My Inventory" as best guess new_selection = getItemByID(gInventory.getRootFolderID()); // ... except if it's hidden from the UI. - if (new_selection && new_selection->getDontShowInHierarchy()) + if (new_selection && new_selection->getHidden()) { new_selection = NULL; } @@ -1822,6 +1823,13 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + // When there are no visible children drag and drop is handled + // by the folder which is the hierarchy root. + if (!handled && !hasVisibleChildren()) + { + handled = mFolders.front()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); + } + if (handled) { lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index bfd9d6dca7..9d54aafd67 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -136,7 +136,7 @@ LLFolderViewItem::LLFolderViewItem(LLFolderViewItem::Params p) mListener(p.listener), mArrowImage(p.folder_arrow_image), mBoxImage(p.selection_image), - mDontShowInHierarchy(false), + mHidden(false), mShowLoadStatus(false) { refresh(); @@ -201,7 +201,7 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children ); // Skip over items that are invisible or are hidden from the UI. - while(itemp && (!itemp->getVisible() || itemp->getDontShowInHierarchy())) + while(itemp && (!itemp->getVisible() || itemp->getHidden())) { LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children ); if (itemp == next_itemp) @@ -392,10 +392,11 @@ BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* roo // makes sure that this view and it's children are the right size. S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) { + static LLUICachedControl<S32> indentation("FolderIndentation", 0); mIndentation = (getParentFolder() && getParentFolder()->getParentFolder() && getParentFolder()->getParentFolder()->getParentFolder()) - ? mParentFolder->getIndentation() + LEFT_INDENTATION + ? mParentFolder->getIndentation() + indentation : 0; if (mLabelWidthDirty) { @@ -418,7 +419,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) S32 LLFolderViewItem::getItemHeight() { - if (mDontShowInHierarchy) return 0; + if (mHidden) return 0; S32 icon_height = mIcon->getHeight(); S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight()); @@ -823,7 +824,7 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFolderViewItem::draw() { - if (mDontShowInHierarchy) return; + if (mHidden) return; static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); @@ -970,11 +971,26 @@ void LLFolderViewItem::draw() font->renderUTF8( mLabel, 0, text_left, y, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); +// LLViewerInventoryCategory *item = 0; +// if (getListener()) +// item = gInventory.getCategory(getListener()->getUUID()); + bool root_is_loading = false; + if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(),gInventory.getRootFolderID())) + { + // Descendent of my inventory. + root_is_loading = gInventory.myInventoryFetchInProgress(); + } + if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(),gInventory.getLibraryRootFolderID())) + { + // Descendent of library + root_is_loading = gInventory.libraryFetchInProgress(); + } + if ( (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) - || (LLInventoryModel::backgroundFetchActive() && mShowLoadStatus) ) + || (LLInventoryModel::backgroundFetchActive() && root_is_loading && mShowLoadStatus) ) { std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) "; font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor, @@ -1257,7 +1273,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) // filter self only on first pass through LLFolderViewItem::filter( filter ); } - if (mDontShowInHierarchy) + if (mHidden) { setOpen(); } diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index a43096dcb2..6f8c738a59 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -93,7 +93,6 @@ public: static void initClass(); static void cleanupClass(); - // jamesdebug was LLUICtrl::Params struct Params : public LLInitParam::Block<Params, LLView::Params> { Optional<LLUIImage*> icon; @@ -111,7 +110,7 @@ public: // layout constants static const S32 LEFT_PAD = 5; - static const S32 LEFT_INDENTATION = 2; + // LEFT_INDENTATION is set via settings.xml FolderIndentation static const S32 ICON_PAD = 2; static const S32 ICON_WIDTH = 16; static const S32 TEXT_PAD = 1; @@ -162,7 +161,7 @@ protected: LLUIImagePtr mBoxImage; BOOL mIsLoading; LLTimer mTimeSinceRequestStart; - bool mDontShowInHierarchy; + bool mHidden; bool mShowLoadStatus; // helper function to change the selection from the root. @@ -206,8 +205,11 @@ public: // makes sure that this view and it's children are the right size. virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); virtual S32 getItemHeight(); - void setDontShowInHierarchy(bool dont_show) { mDontShowInHierarchy = dont_show; } - bool getDontShowInHierarchy() const { return mDontShowInHierarchy; } + + // Hide the folder from the UI, such as if you want to hide the root + // folder in an inventory panel. + void setHidden(bool hidden) { mHidden = hidden; } + bool getHidden() const { return mHidden; } // applies filters to control visibility of inventory items virtual void filter( LLInventoryFilter& filter); diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index ff75d461df..7dd8ea694e 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -119,6 +119,31 @@ void LLGroupActions::search() } // static +void LLGroupActions::startCall(const LLUUID& group_id) +{ + // create a new group voice session + LLGroupData gdata; + + if (!gAgent.getGroupData(group_id, gdata)) + { + llwarns << "Error getting group data" << llendl; + return; + } + + LLUUID session_id = gIMMgr->addSession(gdata.mName, IM_SESSION_GROUP_START, group_id, true); + if (session_id == LLUUID::null) + { + llwarns << "Error adding session" << llendl; + return; + } + + // start the call + gIMMgr->autoStartCallOnStartup(session_id); + + make_ui_sound("UISndStartIM"); +} + +// static void LLGroupActions::join(const LLUUID& group_id) { LLGroupMgrGroupData* gdatap = diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h index 9750b3e3cb..e99df86cd9 100644 --- a/indra/newview/llgroupactions.h +++ b/indra/newview/llgroupactions.h @@ -99,6 +99,11 @@ public: static bool isInGroup(const LLUUID& group_id); /** + * Start a group voice call. + */ + static void startCall(const LLUUID& group_id); + + /** * Returns true if avatar is in group. * * Note that data about group members is loaded from server. diff --git a/indra/newview/llgroupiconctrl.cpp b/indra/newview/llgroupiconctrl.cpp new file mode 100644 index 0000000000..0b03d49cbc --- /dev/null +++ b/indra/newview/llgroupiconctrl.cpp @@ -0,0 +1,145 @@ +/** + * @file llgroupiconctrl.cpp + * @brief LLGroupIconCtrl class implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llgroupiconctrl.h" + +#include "llagent.h" +/* +#include "llavatarconstants.h" +#include "llcallingcard.h" // for LLAvatarTracker +#include "llavataractions.h" +#include "llmenugl.h" +#include "lluictrlfactory.h" + +#include "llcachename.h" +#include "llagentdata.h" +#include "llimfloater.h" +*/ + +static LLDefaultChildRegistry::Register<LLGroupIconCtrl> g_i("group_icon"); + +LLGroupIconCtrl::Params::Params() +: group_id("group_id") +, draw_tooltip("draw_tooltip", true) +, default_icon_name("default_icon_name") +{ +} + + +LLGroupIconCtrl::LLGroupIconCtrl(const LLGroupIconCtrl::Params& p) +: LLIconCtrl(p) +, mGroupId(LLUUID::null) +, mDrawTooltip(p.draw_tooltip) +, mDefaultIconName(p.default_icon_name) +{ + mPriority = LLViewerFetchedTexture::BOOST_ICON; + + if (p.group_id.isProvided()) + { + LLSD value(p.group_id); + setValue(value); + } + else + { + LLIconCtrl::setValue(mDefaultIconName); + } +} + +LLGroupIconCtrl::~LLGroupIconCtrl() +{ + LLGroupMgr::getInstance()->removeObserver(this); +} + +void LLGroupIconCtrl::setValue(const LLSD& value) +{ + if (value.isUUID()) + { + LLGroupMgr* gm = LLGroupMgr::getInstance(); + if (mGroupId.notNull()) + { + gm->removeObserver(this); + } + + if (mGroupId != value.asUUID()) + { + mGroupId = value.asUUID(); + + // Check if cache already contains image_id for that group + if (!updateFromCache()) + { + LLIconCtrl::setValue(mDefaultIconName); + gm->addObserver(this); + gm->sendGroupPropertiesRequest(mGroupId); + } + } + } + else + { + LLIconCtrl::setValue(value); + } +} + +void LLGroupIconCtrl::changed(LLGroupChange gc) +{ + if (GC_PROPERTIES == gc) + { + updateFromCache(); + } +} + +bool LLGroupIconCtrl::updateFromCache() +{ + LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mGroupId); + if (!group_data) return false; + + if (group_data->mInsigniaID.notNull()) + { + LLIconCtrl::setValue(group_data->mInsigniaID); + } + else + { + LLIconCtrl::setValue(mDefaultIconName); + } + + if (mDrawTooltip && !group_data->mName.empty()) + { + setToolTip(group_data->mName); + } + else + { + setToolTip(LLStringUtil::null); + } + return true; +} + diff --git a/indra/newview/llgroupiconctrl.h b/indra/newview/llgroupiconctrl.h new file mode 100644 index 0000000000..7ac2ca0219 --- /dev/null +++ b/indra/newview/llgroupiconctrl.h @@ -0,0 +1,92 @@ +/** + * @file llgroupiconctrl.h + * @brief LLGroupIconCtrl class declaration + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLGROUPICONCTRL_H +#define LL_LLGROUPICONCTRL_H + +#include "lliconctrl.h" + +#include "llgroupmgr.h" + +/** + * Extends IconCtrl to show group icon wherever it is needed. + * + * It gets icon id by group id from the LLGroupMgr. + * If group data is not loaded yet it subscribes as LLGroupMgr observer and requests necessary data. + */ +class LLGroupIconCtrl + : public LLIconCtrl, public LLGroupMgrObserver +{ +public: + struct Params : public LLInitParam::Block<Params, LLIconCtrl::Params> + { + Optional <LLUUID> group_id; + Optional <bool> draw_tooltip; + Optional <std::string> default_icon_name; + Params(); + }; + +protected: + LLGroupIconCtrl(const Params&); + friend class LLUICtrlFactory; + +public: + virtual ~LLGroupIconCtrl(); + + /** + * Determines group icon id by group id and sets it as icon value. + * + * Icon id is got from the appropriate LLGroupMgrGroupData specified by group UUID. + * If necessary it requests necessary data from the LLGroupMgr. + * + * @params value - if LLUUID - it is processed as group id otherwise base method is called. + */ + virtual void setValue(const LLSD& value); + + // LLGroupMgrObserver observer trigger + virtual void changed(LLGroupChange gc); + + const std::string& getGroupName() const { return mGroupName; } + void setDrawTooltip(bool value) { mDrawTooltip = value;} + + const LLUUID& getGroupId() const { return mGroupId; } + +protected: + LLUUID mGroupId; + std::string mGroupName; + bool mDrawTooltip; + std::string mDefaultIconName; + + bool updateFromCache(); +}; + +#endif // LL_LLGROUPICONCTRL_H diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index ab9db10f38..3ca459a403 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -37,6 +37,7 @@ // libs #include "llbutton.h" #include "lliconctrl.h" +#include "llmenugl.h" #include "lltextbox.h" #include "lltrans.h" @@ -46,6 +47,7 @@ #include "llfloaterreg.h" #include "lltextutil.h" #include "llviewercontrol.h" // for gSavedSettings +#include "llviewermenu.h" // for gMenuHolder static LLDefaultChildRegistry::Register<LLGroupList> r("group_list"); S32 LLGroupListItem::sIconWidth = 0; @@ -88,11 +90,24 @@ LLGroupList::LLGroupList(const Params& p) // Set default sort order. setComparator(&GROUP_COMPARATOR); + + // Set up context menu. + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + + registrar.add("People.Groups.Action", boost::bind(&LLGroupList::onContextMenuItemClick, this, _2)); + enable_registrar.add("People.Groups.Enable", boost::bind(&LLGroupList::onContextMenuItemEnable, this, _2)); + + LLMenuGL* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups.xml", + gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if(context_menu) + mContextMenuHandle = context_menu->getHandle(); } LLGroupList::~LLGroupList() { gAgent.removeListener(this); + LLView::deleteViewByHandle(mContextMenuHandle); } // virtual @@ -104,6 +119,22 @@ void LLGroupList::draw() LLFlatListView::draw(); } +// virtual +BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); + + LLMenuGL* context_menu = (LLMenuGL*)mContextMenuHandle.get(); + if (context_menu) + { + context_menu->buildDrawLabels(); + context_menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, context_menu, x, y); + } + + return handled; +} + void LLGroupList::setNameFilter(const std::string& filter) { if (mNameFilter != filter) @@ -203,6 +234,46 @@ bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& return false; } +bool LLGroupList::onContextMenuItemClick(const LLSD& userdata) +{ + std::string action = userdata.asString(); + LLUUID selected_group = getSelectedUUID(); + + if (action == "view_info") + { + LLGroupActions::show(selected_group); + } + else if (action == "chat") + { + LLGroupActions::startIM(selected_group); + } + else if (action == "call") + { + LLGroupActions::startCall(selected_group); + } + else if (action == "activate") + { + LLGroupActions::activate(selected_group); + } + else if (action == "leave") + { + LLGroupActions::leave(selected_group); + } + + return true; +} + +bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata) +{ + LLUUID selected_group_id = getSelectedUUID(); + bool real_group_selected = selected_group_id.notNull(); // a "real" (not "none") group is selected + + if (userdata.asString() == "activate") + return real_group_selected && gAgent.getGroupID() != selected_group_id; + + return real_group_selected; +} + /************************************************************************/ /* LLGroupListItem implementation */ /************************************************************************/ diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 33cfe005b9..f7afe0c0b2 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -60,6 +60,7 @@ public: virtual ~LLGroupList(); virtual void draw(); // from LLView + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); // from LLView void setNameFilter(const std::string& filter); void toggleIcons(); @@ -71,6 +72,11 @@ private: void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM); bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes + bool onContextMenuItemClick(const LLSD& userdata); + bool onContextMenuItemEnable(const LLSD& userdata); + + LLHandle<LLView> mContextMenuHandle; + bool mShowIcons; bool mDirty; std::string mNameFilter; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index acaa6076f8..259f629bdd 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -45,6 +45,7 @@ #include "llfloaterchat.h" #include "llfloaterreg.h" #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container +#include "lllayoutstack.h" #include "lllineeditor.h" #include "lllogchat.h" #include "llpanelimcontrolpanel.h" @@ -56,6 +57,7 @@ #include "llvoicechannel.h" #include "lltransientfloatermgr.h" #include "llinventorymodel.h" +#include "llrootview.h" @@ -107,6 +109,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) default: break; } } + setOverlapsScreenChannel(true); } void LLIMFloater::onFocusLost() @@ -220,6 +223,12 @@ LLIMFloater::~LLIMFloater() //virtual BOOL LLIMFloater::postBuild() { + // User-resizable control panels in P2P sessions look ugly (EXT-3470). + if (mDialog == IM_NOTHING_SPECIAL || mDialog == IM_SESSION_P2P_INVITE) + { + getChild<LLLayoutStack>("im_panels")->setPanelUserResize("panel_im_control_panel", FALSE); + } + const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID); if (other_party_id.notNull()) { @@ -437,6 +446,16 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) void LLIMFloater::getAllowedRect(LLRect& rect) { rect = gViewerWindow->getWorldViewRectRaw(); + static S32 right_padding = 0; + if (right_padding == 0) + { + LLPanel* side_bar_tabs = + gViewerWindow->getRootView()->getChild<LLPanel> ( + "side_bar_tabs"); + right_padding = side_bar_tabs->getRect().getWidth(); + LLTransientFloaterMgr::getInstance()->addControlView(side_bar_tabs); + } + rect.mRight -= right_padding; } void LLIMFloater::setDocked(bool docked, bool pop_on_undock) diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 8b6762ce38..029ddbaf2c 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -55,15 +55,12 @@ #include "llgroupactions.h" #include "llfloater.h" #include "llfloateractivespeakers.h" -#include "llfloatercall.h" #include "llavataractions.h" -#include "llimview.h" #include "llinventory.h" #include "llinventorymodel.h" #include "llfloaterinventory.h" #include "llfloaterchat.h" #include "lliconctrl.h" -#include "llimview.h" // for LLIMModel to get other avatar id in chat #include "llkeyboard.h" #include "lllineeditor.h" #include "llpanelimcontrolpanel.h" diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index b8f99d45c9..abbf1e68ab 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -33,7 +33,6 @@ #ifndef LL_IMPANEL_H #define LL_IMPANEL_H -#include "llimview.h" //for LLIMModel #include "lldockablefloater.h" #include "lllogchat.h" #include "lluuid.h" diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index f5362acbfe..40227539d0 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -57,6 +57,7 @@ #include "llhttpnode.h" #include "llimfloater.h" #include "llimpanel.h" +#include "llgroupiconctrl.h" #include "llresizebar.h" #include "lltabcontainer.h" #include "llviewercontrol.h" @@ -243,10 +244,13 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES std::string joined_call = LLTrans::getString("joined_call"); std::string other_avatar_name = ""; + std::string message; + switch(mSessionType) { case AVALINE_SESSION: - // *TODO: test avaline calls (EXT-2211) + // no text notifications + break; case P2P_SESSION: gCacheName->getFullName(mOtherParticipantID, other_avatar_name); @@ -255,10 +259,13 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES switch(new_state) { case LLVoiceChannel::STATE_CALL_STARTED : - LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, started_call); + message = other_avatar_name + " " + started_call; + LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message); + break; case LLVoiceChannel::STATE_CONNECTED : - LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), joined_call); + message = you + " " + joined_call; + LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message); default: break; } @@ -268,37 +275,27 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES switch(new_state) { case LLVoiceChannel::STATE_CALL_STARTED : - LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), started_call); + message = you + " " + started_call; + LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message); break; case LLVoiceChannel::STATE_CONNECTED : - LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, joined_call); + message = other_avatar_name + " " + joined_call; + LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message); default: break; } } - - // Update speakers list when connected - if (LLVoiceChannel::STATE_CONNECTED == new_state) - { - mSpeakers->update(true); - } - break; case GROUP_SESSION: case ADHOC_SESSION: - // *TODO: determine call starter's name "other_avatar_name" (EXT-2211) - // decide how to show notifications for a group/adhoc chat already opened - // for now there is no notification from voice channel for this case if(direction == LLVoiceChannel::INCOMING_CALL) { switch(new_state) { - case LLVoiceChannel::STATE_CALL_STARTED : - LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, started_call); - break; case LLVoiceChannel::STATE_CONNECTED : - LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), joined_call); + message = you + " " + joined_call; + LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message); default: break; } @@ -308,19 +305,18 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES switch(new_state) { case LLVoiceChannel::STATE_CALL_STARTED : - LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), started_call); + message = you + " " + started_call; + LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message); break; default: break; } } - - // Update speakers list when connected - if (LLVoiceChannel::STATE_CONNECTED == new_state) - { - mSpeakers->update(true); - } - break; + } + // Update speakers list when connected + if (LLVoiceChannel::STATE_CONNECTED == new_state) + { + mSpeakers->update(true); } } @@ -429,6 +425,61 @@ LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const (LLIMModel::LLIMSession*) NULL); } +//*TODO consider switching to using std::set instead of std::list for holding LLUUIDs across the whole code +LLIMModel::LLIMSession* LLIMModel::findAdHocIMSession(const std::vector<LLUUID>& ids) +{ + S32 num = ids.size(); + if (!num) return NULL; + + if (mId2SessionMap.empty()) return NULL; + + std::map<LLUUID, LLIMSession*>::const_iterator it = mId2SessionMap.begin(); + for (; it != mId2SessionMap.end(); ++it) + { + LLIMSession* session = (*it).second; + + if (!session->isAdHoc()) continue; + if (session->mInitialTargetIDs.size() != num) continue; + + std::list<LLUUID> tmp_list(session->mInitialTargetIDs.begin(), session->mInitialTargetIDs.end()); + + std::vector<LLUUID>::const_iterator iter = ids.begin(); + while (iter != ids.end()) + { + tmp_list.remove(*iter); + ++iter; + + if (tmp_list.empty()) + { + break; + } + } + + if (tmp_list.empty() && iter == ids.end()) + { + return session; + } + } + + return NULL; +} + +bool LLIMModel::LLIMSession::isAdHoc() +{ + return IM_SESSION_CONFERENCE_START == mType || (IM_SESSION_INVITE == mType && !gAgent.isInGroup(mSessionID)); +} + +bool LLIMModel::LLIMSession::isP2P() +{ + return IM_NOTHING_SPECIAL == mType; +} + +bool LLIMModel::LLIMSession::isOtherParticipantAvaline() +{ + return !mOtherParticipantIsAvatar; +} + + void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id) { LLIMSession* session = findIMSession(old_session_id); @@ -1227,15 +1278,15 @@ LLIMMgr::showSessionEventError( const std::string& error_string, const LLUUID session_id) { - const LLFloater* floater = getFloaterBySessionID (session_id); - if (!floater) return; - LLSD args; + LLStringUtil::format_map_t event_args; + + event_args["RECIPIENT"] = LLIMModel::getInstance()->getName(session_id); + args["REASON"] = LLTrans::getString(error_string); args["EVENT"] = - LLTrans::getString(event_string); - args["RECIPIENT"] = floater->getTitle(); + LLTrans::getString(event_string, event_args); LLNotificationsUtil::add( "ChatterBoxSessionEventError", @@ -1403,11 +1454,20 @@ void LLCallDialog::getAllowedRect(LLRect& rect) rect = gViewerWindow->getWorldViewRectScaled(); } -void LLCallDialog::onOpen(const LLSD& key) +BOOL LLCallDialog::postBuild() { + if (!LLDockableFloater::postBuild()) + return FALSE; + // dock the dialog to the Speak Button, where other sys messages appear - setDockControl(new LLDockControl(LLBottomTray::getInstance()->getChild<LLPanel>("speak_panel"), - this, getDockTongue(), LLDockControl::TOP, boost::bind(&LLCallDialog::getAllowedRect, this, _1))); + LLView *anchor_panel = LLBottomTray::getInstance()->getChild<LLView>("speak_panel"); + + setDockControl(new LLDockControl( + anchor_panel, this, + getDockTongue(), LLDockControl::TOP, + boost::bind(&LLCallDialog::getAllowedRect, this, _1))); + + return TRUE; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1423,13 +1483,45 @@ LLCallDialog(payload) } } -void LLOutgoingCallDialog::draw() +void LLCallDialog::draw() { if (lifetimeHasExpired()) { onLifetimeExpired(); } - LLDockableFloater::draw(); + + if (getDockControl() != NULL) + { + LLDockableFloater::draw(); + } +} + +void LLCallDialog::setIcon(const LLSD& session_id, const LLSD& participant_id) +{ + // *NOTE: 12/28/2009: check avaline calls: LLVoiceClient::isParticipantAvatar returns false for them + bool participant_is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id); + + bool is_group = participant_is_avatar && gAgent.isInGroup(session_id); + + LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); + LLGroupIconCtrl* group_icon = getChild<LLGroupIconCtrl>("group_icon"); + + avatar_icon->setVisible(!is_group); + group_icon->setVisible(is_group); + + if (is_group) + { + group_icon->setValue(session_id); + } + else if (participant_is_avatar) + { + avatar_icon->setValue(participant_id); + } + else + { + avatar_icon->setValue("Avaline_Icon"); + avatar_icon->setToolTip(std::string("")); + } } bool LLOutgoingCallDialog::lifetimeHasExpired() @@ -1437,7 +1529,7 @@ bool LLOutgoingCallDialog::lifetimeHasExpired() if (mLifetimeTimer.getStarted()) { F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32(); - if (elapsed_time > LIFETIME) + if (elapsed_time > mLifetime) { return true; } @@ -1458,6 +1550,13 @@ void LLOutgoingCallDialog::show(const LLSD& key) // hide all text at first hideAllText(); + // init notification's lifetime + std::istringstream ss( getString("lifetime") ); + if (!(ss >> mLifetime)) + { + mLifetime = DEFAULT_LIFETIME; + } + // customize text strings // tell the user which voice channel they are leaving if (!mPayload["old_channel_name"].asString().empty()) @@ -1486,8 +1585,9 @@ void LLOutgoingCallDialog::show(const LLSD& key) LLSD callee_id = mPayload["other_user_id"]; childSetTextArg("calling", "[CALLEE_NAME]", callee_name); childSetTextArg("connecting", "[CALLEE_NAME]", callee_name); - LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon"); - icon->setValue(callee_id); + + // for outgoing group calls callee_id == group id == session id + setIcon(callee_id, callee_id); // stop timer by default mLifetimeTimer.stop(); @@ -1551,7 +1651,7 @@ void LLOutgoingCallDialog::onCancel(void* user_data) BOOL LLOutgoingCallDialog::postBuild() { - BOOL success = LLDockableFloater::postBuild(); + BOOL success = LLCallDialog::postBuild(); childSetAction("Cancel", onCancel, this); @@ -1568,14 +1668,50 @@ LLCallDialog(payload) { } +bool LLIncomingCallDialog::lifetimeHasExpired() +{ + if (mLifetimeTimer.getStarted()) + { + F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32(); + if (elapsed_time > mLifetime) + { + return true; + } + } + return false; +} + +void LLIncomingCallDialog::onLifetimeExpired() +{ + // check whether a call is valid or not + if (LLVoiceClient::getInstance()->findSession(mPayload["caller_id"].asUUID())) + { + // restart notification's timer if call is still valid + mLifetimeTimer.start(); + } + else + { + // close invitation if call is already not valid + mLifetimeTimer.stop(); + closeFloater(); + } +} + BOOL LLIncomingCallDialog::postBuild() { - LLDockableFloater::postBuild(); + LLCallDialog::postBuild(); LLUUID session_id = mPayload["session_id"].asUUID(); LLSD caller_id = mPayload["caller_id"]; std::string caller_name = mPayload["caller_name"].asString(); + // init notification's lifetime + std::istringstream ss( getString("lifetime") ); + if (!(ss >> mLifetime)) + { + mLifetime = DEFAULT_LIFETIME; + } + std::string call_type; if (gAgent.isInGroup(session_id)) { @@ -1605,14 +1741,24 @@ BOOL LLIncomingCallDialog::postBuild() LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name"); caller_name_widget->setValue(caller_name + " " + call_type); - LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon"); - icon->setValue(caller_id); + setIcon(session_id, caller_id); childSetAction("Accept", onAccept, this); childSetAction("Reject", onReject, this); childSetAction("Start IM", onStartIM, this); childSetFocus("Accept"); + std::string notify_box_type = mPayload["notify_box_type"].asString(); + if(notify_box_type != "VoiceInviteGroup" && notify_box_type != "VoiceInviteAdHoc") + { + // starting notification's timer for P2P and AVALINE invitations + mLifetimeTimer.start(); + } + else + { + mLifetimeTimer.stop(); + } + return TRUE; } @@ -1743,6 +1889,14 @@ void LLIncomingCallDialog::processCallResponse(S32 response) new LLViewerChatterBoxInvitationAcceptResponder( session_id, inv_type)); + + // send notification message to the corresponding chat + if (mPayload["notify_box_type"].asString() == "VoiceInviteGroup" || mPayload["notify_box_type"].asString() == "VoiceInviteAdHoc") + { + std::string started_call = LLTrans::getString("started_call"); + std::string message = mPayload["caller_name"].asString() + " " + started_call; + LLIMModel::getInstance()->addMessageSilently(session_id, SYSTEM_FROM, LLUUID::null, message); + } } } if (voice) @@ -2097,7 +2251,13 @@ BOOL LLIMMgr::getIMReceived() const void LLIMMgr::autoStartCallOnStartup(const LLUUID& session_id) { LLIMModel::LLIMSession *session = LLIMModel::getInstance()->findIMSession(session_id); - if (session) + if (!session) return; + + if (session->mSessionInitialized) + { + startCall(session_id); + } + else { session->mStartCallOnInitialize = true; } @@ -2159,12 +2319,22 @@ LLUUID LLIMMgr::addSession( bool new_session = !LLIMModel::getInstance()->findIMSession(session_id); + //works only for outgoing ad-hoc sessions + if (new_session && IM_SESSION_CONFERENCE_START == dialog && ids.size()) + { + LLIMModel::LLIMSession* ad_hoc_found = LLIMModel::getInstance()->findAdHocIMSession(ids); + if (ad_hoc_found) + { + new_session = false; + session_id = ad_hoc_found->mSessionID; + } + } + if (new_session) { LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids, voice); } - //*TODO remove this "floater" thing when Communicate Floater's gone LLFloaterIMPanel* floater = findFloaterBySession(session_id); if(!floater) @@ -2394,6 +2564,11 @@ void LLIMMgr::processAgentListUpdates(const LLUUID& session_id, const LLSD& body if (speaker_mgr) { speaker_mgr->updateSpeakers(body); + + // also the same call is added into LLVoiceClient::participantUpdatedEvent because + // sometimes it is called AFTER LLViewerChatterBoxSessionAgentListUpdates::post() + // when moderation state changed too late. See EXT-3544. + speaker_mgr->update(true); } else { diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 09f0c9df71..11860d0efb 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -74,6 +74,10 @@ public: 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); + bool isAdHoc(); + bool isP2P(); + bool isOtherParticipantAvaline(); + LLUUID mSessionID; std::string mName; EInstantMessage mType; @@ -133,6 +137,12 @@ public: */ LLIMSession* findIMSession(const LLUUID& session_id) const; + /** + * Find an Ad-Hoc IM Session with specified participants + * @return first found Ad-Hoc session or NULL if the session does not exist + */ + LLIMSession* findAdHocIMSession(const std::vector<LLUUID>& ids); + /** * Rebind session data to a new session id. */ @@ -476,10 +486,32 @@ public: LLCallDialog(const LLSD& payload); ~LLCallDialog() {} - virtual void onOpen(const LLSD& key); + virtual BOOL postBuild(); + + // check timer state + /*virtual*/ void draw(); protected: + // lifetime timer for a notification + LLTimer mLifetimeTimer; + // notification's lifetime in seconds + S32 mLifetime; + static const S32 DEFAULT_LIFETIME = 5; + virtual bool lifetimeHasExpired() {return false;}; + virtual void onLifetimeExpired() {}; + virtual void getAllowedRect(LLRect& rect); + + /** + * Sets icon depend on session. + * + * If passed session_id is a group id group icon will be shown, otherwise avatar icon for participant_id + * + * @param session_id - UUID of session + * @param participant_id - UUID of other participant + */ + void setIcon(const LLSD& session_id, const LLSD& participant_id); + LLSD mPayload; }; @@ -496,6 +528,8 @@ public: static void onStartIM(void* user_data); private: + /*virtual*/ bool lifetimeHasExpired(); + /*virtual*/ void onLifetimeExpired(); void processCallResponse(S32 response); }; @@ -510,19 +544,11 @@ public: static void onCancel(void* user_data); static const LLUUID OCD_KEY; - // check timer state - /*virtual*/ void draw(); - private: - // hide all text boxes void hideAllText(); - // lifetime timer for NO_ANSWER notification - LLTimer mLifetimeTimer; - // lifetime duration for NO_ANSWER notification - static const S32 LIFETIME = 5; - bool lifetimeHasExpired(); - void onLifetimeExpired(); + /*virtual*/ bool lifetimeHasExpired(); + /*virtual*/ void onLifetimeExpired(); }; // Globals diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3fc2cbecbe..d70221b22a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4555,18 +4555,8 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod } else if (isRemoveAction(action)) { - if (get_is_item_worn(mUUID)) - { - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(mUUID)); - } - } + removeFromAvatar(); + return; } else LLItemBridge::performAction(folder, model, action); } @@ -4949,6 +4939,66 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, delete on_remove_struct; } +/* static */ +void LLWearableBridge::removeAllClothesFromAvatar() +{ + // Remove COF links. + for (S32 itype = WT_SHAPE; itype < WT_COUNT; ++itype) + { + if (itype == WT_SHAPE || itype == WT_SKIN || itype == WT_HAIR || itype == WT_EYES) + continue; + + // MULTI-WEARABLES: fixed to index 0 + LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>( + gAgentWearables.getWearableInventoryItem((EWearableType)itype, 0)); + if (!item) + continue; + const LLUUID &item_id = gInventory.getLinkedItemID(item->getUUID()); + const LLWearable *wearable = gAgentWearables.getWearableFromItemID(item_id); + if (!wearable) + continue; + + // Find and remove this item from the COF. + LLInventoryModel::item_array_t items = gInventory.collectLinkedItems( + item_id, LLAppearanceManager::instance().getCOF()); + llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF. + for (LLInventoryModel::item_array_t::const_iterator iter = items.begin(); + iter != items.end(); + ++iter) + { + const LLViewerInventoryItem *linked_item = (*iter); + const LLUUID &item_id = linked_item->getUUID(); + gInventory.purgeObject(item_id); + } + } + gInventory.notifyObservers(); + + // Remove wearables from gAgentWearables + LLAgentWearables::userRemoveAllClothes(); +} + +/* static */ +void LLWearableBridge::removeItemFromAvatar(LLViewerInventoryItem *item) +{ + if (item) + { + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + LLWearableBridge::onRemoveFromAvatarArrived, + new OnRemoveStruct(item->getUUID())); + } +} + +void LLWearableBridge::removeFromAvatar() +{ + if (get_is_item_worn(mUUID)) + { + LLViewerInventoryItem* item = getItem(); + removeItemFromAvatar(item); + } +} + LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type, const LLUUID& uuid,LLInventoryModel* model) { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 4d83e9b684..cc1fa45b26 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -572,7 +572,10 @@ public: static BOOL canRemoveFromAvatar( void* userdata ); static void onRemoveFromAvatar( void* userdata ); - static void onRemoveFromAvatarArrived( LLWearable* wearable, void* userdata ); + static void onRemoveFromAvatarArrived( LLWearable* wearable, void* userdata ); + static void removeItemFromAvatar(LLViewerInventoryItem *item); + static void removeAllClothesFromAvatar(); + void removeFromAvatar(); protected: LLWearableBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLAssetType::EType asset_type, LLInventoryType::EType inv_type, EWearableType wearable_type) : diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 0a8108899a..711114173c 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -67,6 +67,7 @@ F32 LLInventoryModel::sMaxTimeBetweenFetches = 10.f; BOOL LLInventoryModel::sTimelyFetchPending = FALSE; LLFrameTimer LLInventoryModel::sFetchTimer; S16 LLInventoryModel::sBulkFetchCount = 0; +BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE; // Increment this if the inventory contents change in a non-backwards-compatible way. // For viewer 2, the addition of link items makes a pre-viewer-2 cache incorrect. @@ -1339,8 +1340,7 @@ bool LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id) //Initialize statics. bool LLInventoryModel::isBulkFetchProcessingComplete() { - return ( (sFetchQueue.empty() - && sBulkFetchCount<=0) ? TRUE : FALSE ) ; + return sFetchQueue.empty() && sBulkFetchCount<=0; } class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder @@ -1615,10 +1615,58 @@ void LLInventoryModel::bulkFetch(std::string url) } } +bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) +{ + for (std::deque<LLUUID>::iterator it = sFetchQueue.begin(); + it != sFetchQueue.end(); ++it) + { + const LLUUID& fetch_id = *it; + if (gInventory.isObjectDescendentOf(fetch_id, cat_id)) + return false; + } + return true; +} + +/* static */ +bool LLInventoryModel::libraryFetchStarted() +{ + return sLibraryFetchStarted; +} + +/* static */ +bool LLInventoryModel::libraryFetchCompleted() +{ + return libraryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getLibraryRootFolderID()); +} + +/* static */ +bool LLInventoryModel::libraryFetchInProgress() +{ + return libraryFetchStarted() && !libraryFetchCompleted(); +} + +/* static */ +bool LLInventoryModel::myInventoryFetchStarted() +{ + return sMyInventoryFetchStarted; +} + +/* static */ +bool LLInventoryModel::myInventoryFetchCompleted() +{ + return myInventoryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getRootFolderID()); +} + +/* static */ +bool LLInventoryModel::myInventoryFetchInProgress() +{ + return myInventoryFetchStarted() && !myInventoryFetchCompleted(); +} + // static bool LLInventoryModel::isEverythingFetched() { - return (sAllFoldersFetched ? true : false); + return sAllFoldersFetched; } //static @@ -1637,7 +1685,6 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) if (!sMyInventoryFetchStarted) { sMyInventoryFetchStarted = TRUE; - sFetchQueue.push_back(gInventory.getLibraryRootFolderID()); sFetchQueue.push_back(gInventory.getRootFolderID()); gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); } @@ -1645,7 +1692,6 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) { sLibraryFetchStarted = TRUE; sFetchQueue.push_back(gInventory.getLibraryRootFolderID()); - sFetchQueue.push_back(gInventory.getRootFolderID()); gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); } } @@ -2517,6 +2563,10 @@ void LLInventoryModel::buildParentChildMap() llwarns << "Found " << lost << " lost categories." << llendl; } + const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) != LLUUID::null); + sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin(); + + // Now the items. We allocated in the last step, so now all we // have to do is iterate over the items and put them in the right // place. @@ -2604,6 +2654,33 @@ void LLInventoryModel::buildParentChildMap() cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id); if(catsp) { + // *HACK - fix root inventory folder + // some accounts has pbroken inventory root folders + + std::string name = "My Inventory"; + LLUUID prev_root_id = mRootFolderID; + for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(), + it_end = mParentChildCategoryTree.end(); it != it_end; ++it) + { + cat_array_t* cat_array = it->second; + for (cat_array_t::const_iterator cat_it = cat_array->begin(), + cat_it_end = cat_array->end(); cat_it != cat_it_end; ++cat_it) + { + LLPointer<LLViewerInventoryCategory> category = *cat_it; + + if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY) + continue; + if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) ) + { + if(category->getUUID()!=mRootFolderID) + { + LLUUID& new_inv_root_folder_id = const_cast<LLUUID&>(mRootFolderID); + new_inv_root_folder_id = category->getUUID(); + } + } + } + } + // 'My Inventory', // root of the agent's inv found. // The inv tree is built. @@ -3530,6 +3607,19 @@ void LLInventoryModel::setLibraryOwnerID(const LLUUID& val) mLibraryOwnerID = val; } +// static +BOOL LLInventoryModel::getIsFirstTimeInViewer2() +{ + // Do not call this before parentchild map is built. + if (!gInventory.mIsAgentInvUsable) + { + llwarns << "Parent Child Map not yet built; guessing as first time in viewer2." << llendl; + return TRUE; + } + + return sFirstTimeInViewer2; +} + //---------------------------------------------------------------------------- // *NOTE: DEBUG functionality diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 27bbca493d..39377b4ae2 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -499,9 +499,9 @@ public: // *NOTE: DEBUG functionality void dumpInventory() const; - //////////////////////////////////////////////////////////////////////////////// - // Bulk / Background Fetch + //////////////////////////////////////////////////////////////////////////////// + // Bulk fetch public: // Start and stop background breadth-first fetching of inventory contents. // This gets triggered when performing a filter-search @@ -516,6 +516,14 @@ public: // Add categories to a list to be fetched in bulk. static void bulkFetch(std::string url); + static bool libraryFetchStarted(); + static bool libraryFetchCompleted(); + static bool libraryFetchInProgress(); + + static bool myInventoryFetchStarted(); + static bool myInventoryFetchCompleted(); + static bool myInventoryFetchInProgress(); + private: static BOOL sMyInventoryFetchStarted; static BOOL sLibraryFetchStarted; @@ -525,6 +533,13 @@ private: // completing the fetch once per session should be sufficient static BOOL sBackgroundFetchActive; static S16 sBulkFetchCount; + + //////////////////////////////////////////////////////////////////////////////// + // Login status +public: + static BOOL getIsFirstTimeInViewer2(); +private: + static BOOL sFirstTimeInViewer2; }; // a special inventory model for the agent diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 3c34ba32e2..164e72e621 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -402,9 +402,12 @@ void LLInventoryPanel::modelChanged(U32 mask) // static void LLInventoryPanel::onIdle(void *userdata) { + if (!gInventory.isInventoryUsable()) + return; + LLInventoryPanel *self = (LLInventoryPanel*)userdata; // Inventory just initialized, do complete build - if (!self->mViewsInitialized && gInventory.isInventoryUsable()) + if (!self->mViewsInitialized) { self->initializeViews(); } @@ -502,7 +505,7 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id) // but still have the parent folder present for listener-related operations. if (id == mStartFolderID) { - folderp->setDontShowInHierarchy(TRUE); + folderp->setHidden(TRUE); } } } @@ -625,9 +628,15 @@ BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* accept, std::string& tooltip_msg) { - BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + // If folder view is empty the (x, y) point won't be in its rect + // so the handler must be called explicitly. + if (!mFolders->hasVisibleChildren()) + { + handled = mFolders->handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + if (handled) { mFolders->setDragAndDropThisFrame(); diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 98ca339f0c..404e266806 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -634,6 +634,8 @@ void LLLocationInputCtrl::refreshLocation() { location_name = "???"; } + // store human-readable location to compare it in changeLocationPresentation() + mHumanReadableLocation = location_name; setText(location_name); } @@ -823,11 +825,11 @@ void LLLocationInputCtrl::updateWidgetlayout() void LLLocationInputCtrl::changeLocationPresentation() { - //change location presentation only if user does not select anything and + //change location presentation only if user does not select/past anything and //human-readable region name is being displayed std::string text = mTextEntry->getText(); LLStringUtil::trim(text); - if(mTextEntry && !mTextEntry->hasSelection() && !LLSLURL::isSLURL(text)) + if(mTextEntry && !mTextEntry->hasSelection() && text == mHumanReadableLocation ) { //needs unescaped one mTextEntry->setText(LLAgentUI::buildSLURL(false)); diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h index 0211062b05..7959fab2de 100644 --- a/indra/newview/lllocationinputctrl.h +++ b/indra/newview/lllocationinputctrl.h @@ -169,6 +169,8 @@ private: std::string mAddLandmarkTooltip; std::string mEditLandmarkTooltip; + // this field holds a human-readable form of the location string, it is needed to be able to compare copy-pated value and real location + std::string mHumanReadableLocation; }; #endif diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 2dc9f255d7..24c72c65ce 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -76,6 +76,7 @@ LLLoginInstance::LLLoginInstance() : mDispatcher.add("fail.login", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1)); mDispatcher.add("connect", boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1)); mDispatcher.add("disconnect", boost::bind(&LLLoginInstance::handleDisconnect, this, _1)); + mDispatcher.add("indeterminate", boost::bind(&LLLoginInstance::handleIndeterminate, this, _1)); } LLLoginInstance::~LLLoginInstance() @@ -204,6 +205,8 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event) mTransferRate = event["transfer_rate"].asReal(); } + + // Call the method registered in constructor, if any, for more specific // handling LLEventDispatcher::Callable method(mDispatcher.get(event["change"])); @@ -295,6 +298,22 @@ void LLLoginInstance::handleDisconnect(const LLSD& event) // placeholder } +void LLLoginInstance::handleIndeterminate(const LLSD& event) +{ + // The indeterminate response means that the server + // gave the viewer a new url and params to try. + // The login module handles the retry, but it gives us the + // server response so that we may show + // the user some status. + LLSD message = event.get("data").get("message"); + if(message.isDefined()) + { + LLSD progress_update; + progress_update["desc"] = message; + LLEventPumps::getInstance()->obtain("LLProgressView").post(progress_update); + } +} + bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) { if(accepted) @@ -374,28 +393,6 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) mNotifications->add(notification_name, args, payload, boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2)); } - - /* *NOTE:Mani Experiment with Event API interface. - if(!mUpdateAppResponse) - { - bool make_unique = true; - mUpdateAppResponse.reset(new LLEventStream("logininstance_updateapp", make_unique)); - mUpdateAppResponse->listen("diaupdateDialogCallback", - boost::bind(&LLLoginInstance::updateDialogCallback, - this, _1 - ) - ); - } - - LLSD event; - event["op"] = "requestAdd"; - event["name"] = notification_name; - event["substitutions"] = args; - event["payload"] = payload; - event["reply"] = mUpdateAppResponse->getName(); - - LLEventPumps::getInstance()->obtain("LLNotifications").post(event); - */ } bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& response) diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index 19d7449bc1..c8704eddb4 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -89,6 +89,7 @@ private: void handleLoginFailure(const LLSD& event); void handleLoginSuccess(const LLSD& event); void handleDisconnect(const LLSD& event); + void handleIndeterminate(const LLSD& event); bool handleTOSResponse(bool v, const std::string& key); @@ -107,7 +108,6 @@ private: std::string mSerialNumber; int mLastExecEvent; UpdaterLauncherCallback mUpdaterLauncher; - boost::scoped_ptr<LLEventStream> mUpdateAppResponse; LLEventDispatcher mDispatcher; }; diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 199bd966ef..93f926b5d0 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -39,7 +39,6 @@ #include "llfloaterworldmap.h" #include "lluictrlfactory.h" #include "llurldispatcher.h" -#include "llurlsimstring.h" #include "llviewborder.h" #include "llviewercontrol.h" #include "llviewermedia.h" diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp index 2bb2a3da6f..b8da368bd7 100755 --- a/indra/newview/llmediadataclient.cpp +++ b/indra/newview/llmediadataclient.cpp @@ -164,7 +164,7 @@ void LLMediaDataClient::enqueue(const Request *request) // 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; + LL_DEBUGS("LLMediaDataClientQueue") << "SORTED queue:" << mSortedQueue << LL_ENDL; } else { if (mRoundRobinQueue.size() > mMaxRoundRobinQueueSize) @@ -187,7 +187,7 @@ void LLMediaDataClient::enqueue(const Request *request) // 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; + LL_DEBUGS("LLMediaDataClientQueue") << "RR queue:" << mRoundRobinQueue << LL_ENDL; } else { @@ -226,16 +226,16 @@ bool LLMediaDataClient::processQueueTimer() { LL_DEBUGS("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; + LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() started, SORTED queue is: " << mSortedQueue << LL_ENDL; + LL_DEBUGS("LLMediaDataClientQueue") << "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; + LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() finished, SORTED queue is: " << mSortedQueue << LL_ENDL; + LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() finished, RR queue is: " << mRoundRobinQueue << LL_ENDL; return isEmpty(); } @@ -649,7 +649,7 @@ void LLMediaDataClient::Responder::error(U32 status, const std::string& reason) /*virtual*/ void LLMediaDataClient::Responder::result(const LLSD& content) { - LL_DEBUGS("LLMediaDataClient") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL; + LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL; } ////////////////////////////////////////////////////////////////////////////////////// @@ -703,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_DEBUGS("LLMediaDataClient") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL; + LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL; // Look for an error if (content.has("error")) diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 22201aecb2..0ab3b07aea 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -571,7 +571,7 @@ BOOL LLPanelStandStopFlying::postBuild() mStandButton->setVisible(FALSE); mStopFlyingButton = getChild<LLButton>("stop_fly_btn"); - mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE)); + //mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE)); mStopFlyingButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStopFlyingButtonClick, this)); mStopFlyingButton->setVisible(FALSE); @@ -684,7 +684,6 @@ void LLPanelStandStopFlying::onStopFlyingButtonClick() gAgent.setFlying(FALSE); setFocus(FALSE); // EXT-482 - setVisible(FALSE); } /** diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 6210151d1b..71dc0f9011 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -51,6 +51,8 @@ #include "llsidetray.h" #include "llslurl.h" #include "llurlsimstring.h" +#include "llurlregistry.h" +#include "llurldispatcher.h" #include "llviewerinventory.h" #include "llviewermenu.h" #include "llviewerparcelmgr.h" @@ -58,6 +60,7 @@ #include "llappviewer.h" #include "llviewercontrol.h" #include "llfloatermediabrowser.h" +#include "llweb.h" #include "llinventorymodel.h" #include "lllandmarkactions.h" @@ -543,7 +546,20 @@ void LLNavigationBar::onRegionNameResponse( // Invalid location? if (!region_handle) { - invokeSearch(typed_location); + // handle any secondlife:// SLapps, or + // display http:// URLs in the media browser, or + // anything else is sent to the search floater + if (LLUrlRegistry::instance().isUrl(typed_location)) + { + if (! LLURLDispatcher::dispatchFromTextEditor(typed_location)) + { + LLWeb::loadURL(typed_location); + } + } + else + { + invokeSearch(typed_location); + } return; } diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 3a1ae5bf46..2ad82d3e8e 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -178,6 +178,8 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive) if (!chat.mMuted) { + tmp_chat.mFromName = chat.mFromID != gAgentID ? chat.mFromName : LLTrans::getString("You"); + if (chat.mChatStyle == CHAT_STYLE_IRC) { LLColor4 txt_color = LLUIColorTable::instance().getColor("White"); @@ -196,7 +198,7 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive) } else { - mChatHistory->appendMessage(chat,use_plain_text_chat_history); + mChatHistory->appendMessage(chat, use_plain_text_chat_history); } } diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 169560f688..9e13a626b4 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -335,7 +335,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg) if (tmp_chat.mChatStyle == CHAT_STYLE_IRC) { if(!tmp_chat.mFromName.empty()) - tmp_chat.mText = tmp_chat.mFromName + " " + tmp_chat.mText.substr(3); + tmp_chat.mText = tmp_chat.mFromName + tmp_chat.mText.substr(3); else tmp_chat.mText = tmp_chat.mText.substr(3); } diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index c3df4cbaf4..52de8355e9 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -93,6 +93,19 @@ bool LLAlertHandler::processNotification(const LLSD& notify) if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load") { + if (LLHandlerUtil::canSpawnSessionAndLogToIM(notification)) + { + const std::string name = LLHandlerUtil::getSubstitutionName(notification); + + LLUUID from_id = notification->getPayload()["from_id"]; + + // firstly create session... + LLHandlerUtil::spawnIMSession(name, from_id); + + // ...then log message to have IM Well notified about new message + LLHandlerUtil::logToIMP2P(notification); + } + LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); LLToast::Params p; p.notif_id = notification->getID(); diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 515c86bae8..0fb438bfe9 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -277,6 +277,13 @@ public: static bool canSpawnIMSession(const LLNotificationPtr& notification); /** + * Checks if passed notification can create IM session and be written into it. + * + * This method uses canLogToIM() & canSpawnIMSession(). + */ + static bool canSpawnSessionAndLogToIM(const LLNotificationPtr& notification); + + /** * Writes notification message to IM session. */ static void logToIM(const EInstantMessage& session_type, @@ -298,6 +305,20 @@ public: * Writes notification message to nearby chat. */ static void logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type); + + /** + * Spawns IM session. + */ + static void spawnIMSession(const std::string& name, const LLUUID& from_id); + + /** + * Returns name from the notification's substitution. + * + * Methods gets "NAME" or "[NAME]" from the substitution map. + * + * @param notification - Notification which substitution's name will be returned. + */ + static std::string getSubstitutionName(const LLNotificationPtr& notification); }; } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 5b54092c5c..fba5773602 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -47,11 +47,15 @@ const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"), "ObjectGiveItem"), OBJECT_GIVE_ITEM_UNKNOWN_USER( "ObjectGiveItemUnknownUser"), PAYMENT_RECIVED("PaymentRecived"), ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"), - USER_GIVE_ITEM("UserGiveItem"), OFFER_FRIENDSHIP("OfferFriendship"), + USER_GIVE_ITEM("UserGiveItem"), + INVENTORY_ACCEPTED("InventoryAccepted"), + INVENTORY_DECLINED("InventoryDeclined"), + OFFER_FRIENDSHIP("OfferFriendship"), FRIENDSHIP_ACCEPTED("FriendshipAccepted"), FRIENDSHIP_OFFERED("FriendshipOffered"), FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), - SERVER_OBJECT_MESSAGE("ServerObjectMessage"); + SERVER_OBJECT_MESSAGE("ServerObjectMessage"), + TELEPORT_OFFERED("TeleportOffered"); // static bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) @@ -59,8 +63,11 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) return GRANTED_MODIFY_RIGHTS == notification->getName() || REVOKED_MODIFY_RIGHTS == notification->getName() || PAYMENT_RECIVED == notification->getName() + || OFFER_FRIENDSHIP == notification->getName() || FRIENDSHIP_OFFERED == notification->getName() - || SERVER_OBJECT_MESSAGE == notification->getName(); + || SERVER_OBJECT_MESSAGE == notification->getName() + || INVENTORY_ACCEPTED == notification->getName() + || INVENTORY_DECLINED == notification->getName(); } // static @@ -68,15 +75,25 @@ bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification) { return notification->getType() == "notifytip" && FRIEND_ONLINE != notification->getName() - && FRIEND_OFFLINE != notification->getName(); + && FRIEND_OFFLINE != notification->getName() + && INVENTORY_ACCEPTED != notification->getName() + && INVENTORY_DECLINED != notification->getName(); } // static bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification) { - return ADD_FRIEND_WITH_MESSAGE == notification->getName() - || OFFER_FRIENDSHIP == notification->getName() - || FRIENDSHIP_ACCEPTED == notification->getName(); + return OFFER_FRIENDSHIP == notification->getName() + || FRIENDSHIP_ACCEPTED == notification->getName() + || USER_GIVE_ITEM == notification->getName() + || INVENTORY_ACCEPTED == notification->getName() + || INVENTORY_DECLINED == notification->getName(); +} + +// static +bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification) +{ + return canLogToIM(notification) && canSpawnIMSession(notification); } // static @@ -113,10 +130,7 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type, // static void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification) { - const std::string - name = - notification->getSubstitutions().has("NAME") ? notification->getSubstitutions()["NAME"] - : notification->getSubstitutions()["[NAME]"]; + const std::string name = LLHandlerUtil::getSubstitutionName(notification); const std::string session_name = notification->getPayload().has( "SESSION_NAME") ? notification->getPayload()["SESSION_NAME"].asString() : name; @@ -169,3 +183,23 @@ void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChat } } +// static +void LLHandlerUtil::spawnIMSession(const std::string& name, const LLUUID& from_id) +{ + LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); + + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( + session_id); + if (session == NULL) + { + LLIMMgr::instance().addSession(name, IM_NOTHING_SPECIAL, from_id); + } +} + +// static +std::string LLHandlerUtil::getSubstitutionName(const LLNotificationPtr& notification) +{ + return notification->getSubstitutions().has("NAME") + ? notification->getSubstitutions()["NAME"] + : notification->getSubstitutions()["[NAME]"]; +} diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 4d64c5c0e4..dd66a6c507 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -105,22 +105,11 @@ bool LLOfferHandler::processNotification(const LLSD& notify) { if (LLHandlerUtil::canSpawnIMSession(notification)) { - const std::string name = notification->getSubstitutions().has( - "NAME") ? notification->getSubstitutions()["NAME"] - : notification->getSubstitutions()["[NAME]"]; + const std::string name = LLHandlerUtil::getSubstitutionName(notification); LLUUID from_id = notification->getPayload()["from_id"]; - LLUUID session_id = LLIMMgr::computeSessionID( - IM_NOTHING_SPECIAL, from_id); - - LLIMModel::LLIMSession* session = - LLIMModel::instance().findIMSession(session_id); - if (session == NULL) - { - LLIMMgr::instance().addSession(name, IM_NOTHING_SPECIAL, - from_id); - } + LLHandlerUtil::spawnIMSession(name, from_id); } if (notification->getPayload().has("SUPPRES_TOST") diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 9afaddae82..83a2215ac6 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -101,6 +101,19 @@ bool LLTipHandler::processNotification(const LLSD& notify) } } + const std::string name = notification->getSubstitutions()["NAME"]; + LLUUID from_id = notification->getPayload()["from_id"]; + if (LLHandlerUtil::canLogToIM(notification)) + { + LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, name, name, + notification->getMessage(), from_id, from_id); + } + + if (LLHandlerUtil::canSpawnIMSession(notification)) + { + LLHandlerUtil::spawnIMSession(name, from_id); + } + LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); LLToast::Params p; diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index fa16cb6473..63803469dd 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -64,10 +64,6 @@ LLOutputMonitorCtrl::Params::Params() auto_update("auto_update"), speaker_id("speaker_id") { - draw_border = true; - name = "output_monitor"; - follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP); - mouse_opaque = false; }; LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p) diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index ffe7f57167..f3d6dbbb46 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -179,6 +179,10 @@ void LLPanelAvatarNotes::onOpen(const LLSD& key) void LLPanelAvatarNotes::fillRightsData() { + childSetValue("status_check", FALSE); + childSetValue("map_check", FALSE); + childSetValue("objects_check", FALSE); + const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); // If true - we are viewing friend's profile, enable check boxes and set values. if(relation) @@ -327,6 +331,33 @@ void LLPanelAvatarNotes::onShareButtonClick() //*TODO not implemented. } +LLPanelAvatarNotes::~LLPanelAvatarNotes() +{ + if(getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + } +} + +// virtual, called by LLAvatarTracker +void LLPanelAvatarNotes::changed(U32 mask) +{ + childSetEnabled("teleport", LLAvatarTracker::instance().isBuddyOnline(getAvatarId())); +} + +void LLPanelAvatarNotes::setAvatarId(const LLUUID& id) +{ + if(id.notNull()) + { + if(getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + } + LLPanelProfileTab::setAvatarId(id); + LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); + } +} + ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -392,9 +423,18 @@ void LLPanelProfileTab::onMapButtonClick() void LLPanelProfileTab::updateButtons() { - bool enable_map_btn = LLAvatarTracker::instance().isBuddyOnline(getAvatarId()) - && gAgent.isGodlike() || is_agent_mappable(getAvatarId()); + bool is_avatar_online = LLAvatarTracker::instance().isBuddyOnline(getAvatarId()); + + if(LLAvatarActions::isFriend(getAvatarId())) + { + childSetEnabled("teleport", is_avatar_online); + } + else + { + childSetEnabled("teleport", true); + } + bool enable_map_btn = is_avatar_online && gAgent.isGodlike() || is_agent_mappable(getAvatarId()); childSetEnabled("show_on_map_btn", enable_map_btn); childSetEnabled("call", LLAvatarActions::canCall(getAvatarId())); } @@ -403,6 +443,11 @@ void LLPanelProfileTab::updateButtons() ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// +bool enable_god() +{ + return gAgent.isGodlike(); +} + LLPanelAvatarProfile::LLPanelAvatarProfile() : LLPanelProfileTab() { @@ -423,6 +468,13 @@ BOOL LLPanelAvatarProfile::postBuild() LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("Profile.Pay", boost::bind(&LLPanelAvatarProfile::pay, this)); registrar.add("Profile.Share", boost::bind(&LLPanelAvatarProfile::share, this)); + registrar.add("Profile.Kick", boost::bind(&LLPanelAvatarProfile::kick, this)); + registrar.add("Profile.Freeze", boost::bind(&LLPanelAvatarProfile::freeze, this)); + registrar.add("Profile.Unfreeze", boost::bind(&LLPanelAvatarProfile::unfreeze, this)); + registrar.add("Profile.CSR", boost::bind(&LLPanelAvatarProfile::csr, this)); + + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; + enable.add("Profile.EnableGod", boost::bind(&enable_god)); mProfileMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_profile_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); @@ -622,6 +674,28 @@ void LLPanelAvatarProfile::share() LLAvatarActions::share(getAvatarId()); } +void LLPanelAvatarProfile::kick() +{ + LLAvatarActions::kick(getAvatarId()); +} + +void LLPanelAvatarProfile::freeze() +{ + LLAvatarActions::freeze(getAvatarId()); +} + +void LLPanelAvatarProfile::unfreeze() +{ + LLAvatarActions::unfreeze(getAvatarId()); +} + +void LLPanelAvatarProfile::csr() +{ + std::string name; + gCacheName->getFullName(getAvatarId(), name); + LLAvatarActions::csr(getAvatarId(), name); +} + void LLPanelAvatarProfile::onUrlTextboxClicked(const std::string& url) { LLWeb::loadURL(url); @@ -678,6 +752,33 @@ void LLPanelAvatarProfile::onOverflowButtonClicked() LLMenuGL::showPopup(this, mProfileMenu, rect.mRight, rect.mTop); } +LLPanelAvatarProfile::~LLPanelAvatarProfile() +{ + if(getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + } +} + +// virtual, called by LLAvatarTracker +void LLPanelAvatarProfile::changed(U32 mask) +{ + childSetEnabled("teleport", LLAvatarTracker::instance().isBuddyOnline(getAvatarId())); +} + +void LLPanelAvatarProfile::setAvatarId(const LLUUID& id) +{ + if(id.notNull()) + { + if(getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + } + LLPanelProfileTab::setAvatarId(id); + LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); + } +} + ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index b19c5cca49..22efa5dc35 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -35,6 +35,7 @@ #include "llpanel.h" #include "llavatarpropertiesprocessor.h" +#include "llcallingcard.h" class LLComboBox; class LLLineEditor; @@ -120,13 +121,22 @@ private: */ class LLPanelAvatarProfile : public LLPanelProfileTab + , public LLFriendObserver { public: LLPanelAvatarProfile(); + /*virtual*/ ~LLPanelAvatarProfile(); /*virtual*/ void onOpen(const LLSD& key); /** + * LLFriendObserver trigger + */ + virtual void changed(U32 mask); + + /*virtual*/ void setAvatarId(const LLUUID& id); + + /** * Processes data received from server. */ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); @@ -181,6 +191,15 @@ protected: */ void share(); + void kick(); + void freeze(); + void unfreeze(); + void csr(); + + + bool enableGod(); + + void onUrlTextboxClicked(const std::string& url); void onHomepageTextboxClicked(); void onAddFriendButtonClick(); @@ -237,9 +256,18 @@ private: */ class LLPanelAvatarNotes : public LLPanelProfileTab + , public LLFriendObserver { public: LLPanelAvatarNotes(); + /*virtual*/ ~LLPanelAvatarNotes(); + + virtual void setAvatarId(const LLUUID& id); + + /** + * LLFriendObserver trigger + */ + virtual void changed(U32 mask); /*virtual*/ void onOpen(const LLSD& key); diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index ae703ebd8e..362657a458 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -171,7 +171,7 @@ void LLPanelBlockedList::onPickBtnClick() { const BOOL allow_multiple = FALSE; const BOOL close_on_select = TRUE; - /*LLFloaterAvatarPicker* picker = */LLFloaterAvatarPicker::show(callbackBlockPicked, this, allow_multiple, close_on_select); + /*LLFloaterAvatarPicker* picker = */LLFloaterAvatarPicker::show(boost::bind(&LLPanelBlockedList::callbackBlockPicked, this, _1, _2), allow_multiple, close_on_select); // *TODO: mantipov: should LLFloaterAvatarPicker be closed when panel is closed? // old Floater dependency is not enable in panel @@ -183,8 +183,7 @@ void LLPanelBlockedList::onBlockByNameClick() LLFloaterGetBlockedObjectName::show(&LLPanelBlockedList::callbackBlockByName); } -//static -void LLPanelBlockedList::callbackBlockPicked(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* user_data) +void LLPanelBlockedList::callbackBlockPicked(const std::vector<std::string>& names, const std::vector<LLUUID>& ids) { if (names.empty() || ids.empty()) return; LLMute mute(ids[0], names[0], LLMute::AGENT); diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h index 0993f46f79..1ef16a02f4 100644 --- a/indra/newview/llpanelblockedlist.h +++ b/indra/newview/llpanelblockedlist.h @@ -78,7 +78,7 @@ private: void onPickBtnClick(); void onBlockByNameClick(); - static void callbackBlockPicked(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* user_data); + void callbackBlockPicked(const std::vector<std::string>& names, const std::vector<LLUUID>& ids); static void callbackBlockByName(const std::string& text); private: diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 0dae667e7f..e29320ffc2 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -1557,6 +1557,11 @@ void LLPanelClassifiedEdit::resetControls() childSetValue("price_for_listing", MINIMUM_PRICE_FOR_LISTING); } +bool LLPanelClassifiedEdit::canClose() +{ + return isValidName(); +} + void LLPanelClassifiedEdit::sendUpdate() { LLAvatarClassifiedInfo c_data; @@ -1671,6 +1676,12 @@ void LLPanelClassifiedEdit::onChange() void LLPanelClassifiedEdit::onSaveClick() { + if(!isValidName()) + { + notifyInvalidName(); + return; + } + sendUpdate(); resetDirty(); } @@ -1681,6 +1692,34 @@ std::string LLPanelClassifiedEdit::getLocationNotice() return location_notice; } +bool LLPanelClassifiedEdit::isValidName() +{ + std::string name = getClassifiedName(); + if (name.empty()) + { + return false; + } + if (!isalnum(name[0])) + { + return false; + } + + return true; +} + +void LLPanelClassifiedEdit::notifyInvalidName() +{ + std::string name = getClassifiedName(); + if (name.empty()) + { + LLNotificationsUtil::add("BlankClassifiedName"); + } + else if (!isalnum(name[0])) + { + LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric"); + } +} + void LLPanelClassifiedEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl) { ctrl->setVisible(TRUE); diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h index 8b32495854..10fdf60bbe 100644 --- a/indra/newview/llpanelclassified.h +++ b/indra/newview/llpanelclassified.h @@ -305,6 +305,8 @@ public: bool isNew() { return mIsNew; } + bool canClose(); + protected: LLPanelClassifiedEdit(); @@ -325,6 +327,10 @@ protected: std::string getLocationNotice(); + bool isValidName(); + + void notifyInvalidName(); + void onSetLocationClick(); void onChange(); void onSaveClick(); diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 375ee0fdc4..06a682c905 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -292,8 +292,8 @@ void LLPanelGroupInvite::impl::callbackClickAdd(void* userdata) LLFloater* parentp; parentp = gFloaterView->getParentFloater(panelp); - parentp->addDependentFloater(LLFloaterAvatarPicker::show(callbackAddUsers, - panelp->mImplementation, + parentp->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(impl::callbackAddUsers, _1, _2, + panelp->mImplementation), TRUE)); } } diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index 70e4798079..279818d52f 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -65,7 +65,11 @@ void LLPanelChatControlPanel::onOpenVoiceControlsClicked() void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) { - bool is_call_started = ( new_state >= LLVoiceChannel::STATE_CALL_STARTED ); + updateButtons(new_state >= LLVoiceChannel::STATE_CALL_STARTED); +} + +void LLPanelChatControlPanel::updateButtons(bool is_call_started) +{ childSetVisible("end_call_btn", is_call_started); childSetVisible("voice_ctrls_btn", is_call_started); childSetVisible("call_btn", ! is_call_started); @@ -112,6 +116,9 @@ void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id) if(voice_channel) { mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2)); + + //call (either p2p, group or ad-hoc) can be already in started state + updateButtons(voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); } } @@ -177,6 +184,12 @@ void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id) // Disable "Add friend" button for friends. childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(mAvatarID)); + + // Disable "Teleport" button if friend is offline + if(LLAvatarActions::isFriend(mAvatarID)) + { + childSetEnabled("teleport_btn", LLAvatarTracker::instance().isBuddyOnline(mAvatarID)); + } getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(mAvatarID); @@ -207,6 +220,12 @@ void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id) void LLPanelIMControlPanel::changed(U32 mask) { childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(mAvatarID)); + + // Disable "Teleport" button if friend is offline + if(LLAvatarActions::isFriend(mAvatarID)) + { + childSetEnabled("teleport_btn", LLAvatarTracker::instance().isBuddyOnline(mAvatarID)); + } } void LLPanelIMControlPanel::nameUpdatedCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group) @@ -247,6 +266,9 @@ void LLPanelGroupControlPanel::draw() //Remove event does not raised until speakerp->mActivityTimer.hasExpired() is false, see LLSpeakerManager::update() //so we need update it to raise needed event mSpeakerManager->update(true); + // Need to resort the participant list if it's in sort by recent speaker order. + if (mParticipantList) + mParticipantList->updateRecentSpeakersOrder(); LLPanelChatControlPanel::draw(); } @@ -282,8 +304,9 @@ void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id) mGroupID = LLIMModel::getInstance()->getOtherParticipantID(session_id); + // for group and Ad-hoc chat we need to include agent into list if(!mParticipantList) - mParticipantList = new LLParticipantList(mSpeakerManager, getChild<LLAvatarList>("speakers_list")); + mParticipantList = new LLParticipantList(mSpeakerManager, getChild<LLAvatarList>("speakers_list"), true,false); } diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h index 711340efc7..c18be5a6df 100644 --- a/indra/newview/llpanelimcontrolpanel.h +++ b/indra/newview/llpanelimcontrolpanel.h @@ -57,6 +57,8 @@ public: virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); + void updateButtons(bool is_call_started); + virtual void setSessionId(const LLUUID& session_id); const LLUUID& getSessionId() { return mSessionId; } diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index 5de7c3f851..597b8bdb2d 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -81,7 +81,8 @@ BOOL LLPanelLandmarkInfo::postBuild() mCreator = getChild<LLTextBox>("creator"); mCreated = getChild<LLTextBox>("created"); - mTitleEditor = getChild<LLLineEditor>("title_editor"); + mLandmarkTitle = getChild<LLTextBox>("title_value"); + mLandmarkTitleEditor = getChild<LLLineEditor>("title_editor"); mNotesEditor = getChild<LLTextEditor>("notes_editor"); mFolderCombo = getChild<LLComboBox>("folder_combo"); @@ -101,7 +102,8 @@ void LLPanelLandmarkInfo::resetLocation() mCreator->setText(not_available); mOwner->setText(not_available); mCreated->setText(not_available); - mTitleEditor->setText(LLStringUtil::null); + mLandmarkTitle->setText(LLStringUtil::null); + mLandmarkTitleEditor->setText(LLStringUtil::null); mNotesEditor->setText(LLStringUtil::null); } @@ -122,7 +124,8 @@ void LLPanelLandmarkInfo::setInfoType(INFO_TYPE type) case CREATE_LANDMARK: mCurrentTitle = getString("title_create_landmark"); - mTitleEditor->setEnabled(TRUE); + mLandmarkTitle->setVisible(FALSE); + mLandmarkTitleEditor->setVisible(TRUE); mNotesEditor->setEnabled(TRUE); break; @@ -130,7 +133,8 @@ void LLPanelLandmarkInfo::setInfoType(INFO_TYPE type) default: mCurrentTitle = getString("title_landmark"); - mTitleEditor->setEnabled(FALSE); + mLandmarkTitle->setVisible(TRUE); + mLandmarkTitleEditor->setVisible(FALSE); mNotesEditor->setEnabled(FALSE); break; } @@ -185,12 +189,12 @@ void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data) { if (parcel_data.name.empty()) { - mTitleEditor->setText(llformat("%s (%d, %d, %d)", + mLandmarkTitleEditor->setText(llformat("%s (%d, %d, %d)", parcel_data.sim_name.c_str(), region_x, region_y, region_z)); } else { - mTitleEditor->setText(parcel_data.name); + mLandmarkTitleEditor->setText(parcel_data.name); } std::string desc; @@ -281,7 +285,8 @@ void LLPanelLandmarkInfo::displayItemInfo(const LLInventoryItem* pItem) mCreated->setText(timeStr); } - mTitleEditor->setText(pItem->getName()); + mLandmarkTitle->setText(pItem->getName()); + mLandmarkTitleEditor->setText(pItem->getName()); mNotesEditor->setText(pItem->getDescription()); } @@ -296,11 +301,14 @@ void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled) else { mTitle->setText(mCurrentTitle); + + mLandmarkTitle->setText(mLandmarkTitleEditor->getText()); } if (mNotesEditor->getReadOnly() == (enabled == TRUE)) { - mTitleEditor->setEnabled(enabled); + mLandmarkTitle->setVisible(!enabled); + mLandmarkTitleEditor->setVisible(enabled); mNotesEditor->setReadOnly(!enabled); mFolderCombo->setVisible(enabled); getChild<LLTextBox>("folder_label")->setVisible(enabled); @@ -313,7 +321,7 @@ void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled) const std::string& LLPanelLandmarkInfo::getLandmarkTitle() const { - return mTitleEditor->getText(); + return mLandmarkTitleEditor->getText(); } const std::string LLPanelLandmarkInfo::getLandmarkNotes() const @@ -333,7 +341,7 @@ BOOL LLPanelLandmarkInfo::setLandmarkFolder(const LLUUID& id) void LLPanelLandmarkInfo::createLandmark(const LLUUID& folder_id) { - std::string name = mTitleEditor->getText(); + std::string name = mLandmarkTitleEditor->getText(); std::string desc = mNotesEditor->getText(); LLStringUtil::trim(name); diff --git a/indra/newview/llpanellandmarkinfo.h b/indra/newview/llpanellandmarkinfo.h index 73e0ddb9cc..2a9949ae41 100644 --- a/indra/newview/llpanellandmarkinfo.h +++ b/indra/newview/llpanellandmarkinfo.h @@ -77,7 +77,8 @@ private: LLTextBox* mOwner; LLTextBox* mCreator; LLTextBox* mCreated; - LLLineEditor* mTitleEditor; + LLTextBox* mLandmarkTitle; + LLLineEditor* mLandmarkTitleEditor; LLTextEditor* mNotesEditor; LLComboBox* mFolderCombo; }; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index e16bac2098..30acf37f82 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -49,9 +49,9 @@ #include "llfloaterworldmap.h" #include "llfolderviewitem.h" #include "llinventorypanel.h" -#include "llinventorysubtreepanel.h" #include "lllandmarkactions.h" #include "llplacesinventorybridge.h" +#include "llplacesinventorypanel.h" #include "llsidetray.h" #include "llviewermenu.h" #include "llviewerregion.h" @@ -66,15 +66,54 @@ 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); +static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string); +static bool category_has_descendents(LLPlacesInventoryPanel* 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. + * Functor counting expanded and collapsed folders in folder view tree to know + * when to enable or disable "Expand all folders" and "Collapse all folders" commands. + */ +class LLCheckFolderState : public LLFolderViewFunctor +{ +public: + LLCheckFolderState() + : mCollapsedFolders(0), + mExpandedFolders(0) + {} + virtual ~LLCheckFolderState() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item) {} + S32 getCollapsedFolders() { return mCollapsedFolders; } + S32 getExpandedFolders() { return mExpandedFolders; } + +private: + S32 mCollapsedFolders; + S32 mExpandedFolders; +}; + +// virtual +void LLCheckFolderState::doFolder(LLFolderViewFolder* folder) +{ + // Counting only folders that pass the filter. + // The listener check allow us to avoid counting the folder view + // object itself because it has no listener assigned. + if (folder->hasFilteredDescendants() && folder->getListener()) + { + if (folder->isOpen()) + { + ++mExpandedFolders; + } + else + { + ++mCollapsedFolders; + } + } +} + +/** + * Bridge to support knowing when the inventory has changed to update Landmarks tab + * ShowFolderState filter setting to show all folders when the filter string is empty and + * empty folder message when Landmarks inventory category has no children. */ class LLLandmarksPanelObserver : public LLInventoryObserver { @@ -89,7 +128,7 @@ private: void LLLandmarksPanelObserver::changed(U32 mask) { - mLP->saveFolderStateIfNoFilter(); + mLP->updateShowFolderState(); } LLLandmarksPanel::LLLandmarksPanel() @@ -134,22 +173,12 @@ BOOL LLLandmarksPanel::postBuild() getChild<LLAccordionCtrlTab>("tab_favorites")->setDisplayChildren(true); getChild<LLAccordionCtrlTab>("tab_landmarks")->setDisplayChildren(true); - gIdleCallbacks.addFunction(LLLandmarksPanel::doIdle, this); return TRUE; } // virtual void LLLandmarksPanel::onSearchEdit(const std::string& string) { - // show all folders in Landmarks Accordion for empty filter - if (mLandmarksInventoryPanel->getFilter()) - { - mLandmarksInventoryPanel->setShowFolderState(string.empty() ? - LLInventoryFilter::SHOW_ALL_FOLDERS : - LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS - ); - } - // give FolderView a chance to be refreshed. So, made all accordions visible for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter) { @@ -162,7 +191,7 @@ void LLLandmarksPanel::onSearchEdit(const std::string& string) tab->changeOpenClose(false); } - LLInventorySubTreePanel* inventory_list = dynamic_cast<LLInventorySubTreePanel*>(tab->getAccordionView()); + LLPlacesInventoryPanel* inventory_list = dynamic_cast<LLPlacesInventoryPanel*>(tab->getAccordionView()); if (NULL == inventory_list) continue; if (inventory_list->getFilter()) @@ -173,6 +202,10 @@ void LLLandmarksPanel::onSearchEdit(const std::string& string) if (sFilterSubString != string) sFilterSubString = string; + + // show all folders in Landmarks Accordion for empty filter + // only if Landmarks inventory folder is not empty + updateShowFolderState(); } // virtual @@ -226,7 +259,7 @@ void LLLandmarksPanel::updateVerbs() updateListCommands(); } -void LLLandmarksPanel::onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action) +void LLLandmarksPanel::onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action) { if (user_action && (items.size() > 0)) { @@ -254,12 +287,21 @@ void LLLandmarksPanel::onSelectorButtonClicked() } } -void LLLandmarksPanel::saveFolderStateIfNoFilter() +void LLLandmarksPanel::updateShowFolderState() { - 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); + if (!mLandmarksInventoryPanel->getFilter()) + return; + + bool show_all_folders = mLandmarksInventoryPanel->getRootFolder()->getFilterSubString().empty(); + if (show_all_folders) + { + show_all_folders = category_has_descendents(mLandmarksInventoryPanel); + } + + mLandmarksInventoryPanel->setShowFolderState(show_all_folders ? + LLInventoryFilter::SHOW_ALL_FOLDERS : + LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS + ); } ////////////////////////////////////////////////////////////////////////// @@ -361,7 +403,7 @@ void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason) void LLLandmarksPanel::initFavoritesInventoryPanel() { - mFavoritesInventoryPanel = getChild<LLInventorySubTreePanel>("favorites_list"); + mFavoritesInventoryPanel = getChild<LLPlacesInventoryPanel>("favorites_list"); initLandmarksPanel(mFavoritesInventoryPanel); mFavoritesInventoryPanel->getFilter()->setEmptyLookupMessage("FavoritesNoMatchingItems"); @@ -371,7 +413,7 @@ void LLLandmarksPanel::initFavoritesInventoryPanel() void LLLandmarksPanel::initLandmarksInventoryPanel() { - mLandmarksInventoryPanel = getChild<LLInventorySubTreePanel>("landmarks_list"); + mLandmarksInventoryPanel = getChild<LLPlacesInventoryPanel>("landmarks_list"); initLandmarksPanel(mLandmarksInventoryPanel); @@ -390,7 +432,7 @@ void LLLandmarksPanel::initLandmarksInventoryPanel() void LLLandmarksPanel::initMyInventoryPanel() { - mMyInventoryPanel= getChild<LLInventorySubTreePanel>("my_inventory_list"); + mMyInventoryPanel= getChild<LLPlacesInventoryPanel>("my_inventory_list"); initLandmarksPanel(mMyInventoryPanel); @@ -399,14 +441,14 @@ void LLLandmarksPanel::initMyInventoryPanel() void LLLandmarksPanel::initLibraryInventoryPanel() { - mLibraryInventoryPanel = getChild<LLInventorySubTreePanel>("library_list"); + mLibraryInventoryPanel = getChild<LLPlacesInventoryPanel>("library_list"); initLandmarksPanel(mLibraryInventoryPanel); initAccordion("tab_library", mLibraryInventoryPanel); } -void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_list) +void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list) { // In case of a dummy widget further we have no Folder View widget and no Filter, // so further initialization leads to crash. @@ -430,7 +472,7 @@ void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_lis inventory_list->saveFolderState(); } -void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list) +void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list) { LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name); @@ -440,7 +482,7 @@ void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLIn accordion_tab->setDisplayChildren(false); } -void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list) +void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list) { bool expanded = param.asBoolean(); @@ -463,10 +505,14 @@ void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInvento { gInventory.startBackgroundFetch(cat_id); } + + // Apply filter substring because it might have been changed + // while accordion was closed. See EXT-3714. + filter_list(inventory_list, sFilterSubString); } } -void LLLandmarksPanel::deselectOtherThan(const LLInventorySubTreePanel* inventory_list) +void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory_list) { if (inventory_list != mFavoritesInventoryPanel) { @@ -660,7 +706,12 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) } else if ("collapse_all" == command_name) { - root_folder->closeAllFolders(); + root_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); + + // The top level folder is invisible, it must be open to + // display its sub-folders. + root_folder->openTopLevelFolders(); + root_folder->arrangeAll(); } else if ( "sort_by_date" == command_name) { @@ -722,6 +773,20 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const return false; } + LLCheckFolderState checker; + rootFolderView->applyFunctorRecursively(checker); + + // We assume that the root folder is always expanded so we enable "collapse_all" + // command when we have at least one more expanded folder. + if (checker.getExpandedFolders() < 2 && "collapse_all" == command_name) + { + return false; + } + + if (checker.getCollapsedFolders() < 1 && "expand_all" == command_name) + { + return false; + } if("category" == command_name) { @@ -778,46 +843,6 @@ void LLLandmarksPanel::onCustomAction(const LLSD& userdata) } } -void LLLandmarksPanel::updateFilteredAccordions() -{ - LLInventoryPanel* inventory_list = NULL; - LLAccordionCtrlTab* accordion_tab = NULL; - bool needs_arrange = false; - - for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter) - { - accordion_tab = *iter; - - accordion_tab->setVisible(TRUE); - - inventory_list = dynamic_cast<LLInventorySubTreePanel*> (accordion_tab->getAccordionView()); - 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 - fv->arrangeFromRoot(); - - bool has_descendants = fv->hasFilteredDescendants(); - if (!has_descendants) - needs_arrange = true; - - accordion_tab->setVisible(has_descendants); - - //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) - { - static LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion"); - accordion->arrange(); - } -} - /* Processes such actions: cut/rename/delete/paste actions @@ -926,13 +951,6 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg return true; } -// static -void LLLandmarksPanel::doIdle(void* landmarks_panel) -{ - LLLandmarksPanel* panel = (LLLandmarksPanel* ) landmarks_panel; - panel->updateFilteredAccordions(); -} - void LLLandmarksPanel::doShowOnMap(LLLandmark* landmark) { LLVector3d landmark_global_pos; @@ -1028,10 +1046,10 @@ void LLLandmarksPanel::doCreatePick(LLLandmark* landmark) ////////////////////////////////////////////////////////////////////////// // HELPER FUNCTIONS ////////////////////////////////////////////////////////////////////////// -static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string) +static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string) { // When search is cleared, restore the old folder state. - if (string == "") + if (!inventory_list->getRootFolder()->getFilterSubString().empty() && string == "") { inventory_list->setFilterSubString(LLStringUtil::null); // Re-open folders that were open before @@ -1056,15 +1074,16 @@ static void filter_list(LLInventorySubTreePanel* inventory_list, const std::stri // Set new filter string inventory_list->setFilterSubString(string); - } -static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list) +static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list) { - // save current folder open state if no filter currently applied - if (inventory_list->getRootFolder() && inventory_list->getRootFolder()->getFilterSubString().empty()) + LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getStartFolderID()); + if (category) { - // inventory_list->saveFolderState(); // *TODO: commented out to fix build + return category->getDescendentCount() > 0; } + + return false; } // EOF diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index b0e537f647..569739237d 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -46,7 +46,7 @@ class LLAccordionCtrlTab; class LLFolderViewItem; class LLMenuGL; class LLInventoryPanel; -class LLInventorySubTreePanel; +class LLPlacesInventoryPanel; class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver { @@ -60,17 +60,18 @@ public: /*virtual*/ void onTeleport(); /*virtual*/ void updateVerbs(); - void onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action); + void onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action); void onSelectorButtonClicked(); - void setCurrentSelectedList(LLInventorySubTreePanel* inventory_list) + void setCurrentSelectedList(LLPlacesInventoryPanel* inventory_list) { mCurrentSelectedList = inventory_list; } /** - * Saves folder state for all Inventory Panels if there are no applied filter. + * Update filter ShowFolderState setting to show empty folder message + * if Landmarks inventory folder is empty. */ - void saveFolderStateIfNoFilter(); + void updateShowFolderState(); protected: /** @@ -92,10 +93,10 @@ private: void initLandmarksInventoryPanel(); void initMyInventoryPanel(); void initLibraryInventoryPanel(); - void initLandmarksPanel(LLInventorySubTreePanel* inventory_list); - void initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list); - void onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list); - void deselectOtherThan(const LLInventorySubTreePanel* inventory_list); + void initLandmarksPanel(LLPlacesInventoryPanel* inventory_list); + void initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list); + void onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list); + void deselectOtherThan(const LLPlacesInventoryPanel* inventory_list); // List Commands Handlers void initListCommandsHandlers(); @@ -112,13 +113,6 @@ private: void onCustomAction(const LLSD& command_name); /** - * Updates accordions according to filtered items in lists. - * - * It hides accordion for empty lists - */ - void updateFilteredAccordions(); - - /** * Determines if selected item can be modified via context/gear menu. * * It validates Places Landmarks rules first. And then LLFolderView permissions. @@ -133,11 +127,6 @@ private: bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept); /** - * Static callback for gIdleCallbacks to perform actions out of drawing - */ - static void doIdle(void* landmarks_panel); - - /** * Landmark actions callbacks. Fire when a landmark is loaded from the list. */ void doShowOnMap(LLLandmark* landmark); @@ -148,14 +137,14 @@ private: void doCreatePick(LLLandmark* landmark); private: - LLInventorySubTreePanel* mFavoritesInventoryPanel; - LLInventorySubTreePanel* mLandmarksInventoryPanel; - LLInventorySubTreePanel* mMyInventoryPanel; - LLInventorySubTreePanel* mLibraryInventoryPanel; + LLPlacesInventoryPanel* mFavoritesInventoryPanel; + LLPlacesInventoryPanel* mLandmarksInventoryPanel; + LLPlacesInventoryPanel* mMyInventoryPanel; + LLPlacesInventoryPanel* mLibraryInventoryPanel; LLMenuGL* mGearLandmarkMenu; LLMenuGL* mGearFolderMenu; LLMenuGL* mMenuAdd; - LLInventorySubTreePanel* mCurrentSelectedList; + LLPlacesInventoryPanel* mCurrentSelectedList; LLInventoryObserver* mInventoryObserver; LLPanel* mListCommands; diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index ce83ab3e37..af9e791223 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 "llurlsimstring.h" #include "lluictrlfactory.h" #include "llhttpclient.h" #include "llweb.h" @@ -229,8 +228,12 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, LLComboBox* combo = getChild<LLComboBox>("start_location_combo"); - LLURLSimString::setString(gSavedSettings.getString("LoginLocation")); std::string sim_string = LLURLSimString::sInstance.mSimString; + if(sim_string.empty()) + { + LLURLSimString::setString(gSavedSettings.getString("LoginLocation")); + } + if (!sim_string.empty()) { // Replace "<Type region name>" with this region name diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 961d3dec8b..e74a39c85c 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -35,6 +35,7 @@ #include "llagent.h" #include "lldndbutton.h" +#include "lleconomy.h" #include "llfilepicker.h" #include "llfloaterinventory.h" #include "llinventorybridge.h" @@ -97,7 +98,8 @@ LLPanelMainInventory::LLPanelMainInventory() mSavedFolderState(NULL), mFilterText(""), mMenuGearDefault(NULL), - mMenuAdd(NULL) + mMenuAdd(NULL), + mNeedUploadCost(true) { LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_INIT); // Menu Callbacks (non contex menus) @@ -895,6 +897,8 @@ void LLPanelMainInventory::onGearButtonClick() void LLPanelMainInventory::onAddButtonClick() { + setUploadCostIfNeeded(); + showActionMenu(mMenuAdd,"add_btn"); } @@ -1131,5 +1135,39 @@ bool LLPanelMainInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType return true; } +void LLPanelMainInventory::setUploadCostIfNeeded() +{ + // *NOTE dzaporozhan + // Upload cost is set in process_economy_data() (llviewermessage.cpp). But since we + // have two instances of Inventory panel at the moment(and two instances of context menu), + // call to gMenuHolder->childSetLabelArg() sets upload cost only for one of the instances. + + if(mNeedUploadCost && mMenuAdd) + { + LLMenuItemBranchGL* upload_menu = mMenuAdd->findChild<LLMenuItemBranchGL>("upload"); + if(upload_menu) + { + S32 upload_cost = -1;//LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + std::string cost_str; + + // getPriceUpload() returns -1 if no data available yet. + if(upload_cost >= 0) + { + mNeedUploadCost = false; + cost_str = llformat("%d", upload_cost); + } + else + { + cost_str = llformat("%d", gSavedSettings.getU32("DefaultUploadCost")); + } + + upload_menu->getChild<LLView>("Upload Image")->setLabelArg("[COST]", cost_str); + upload_menu->getChild<LLView>("Upload Sound")->setLabelArg("[COST]", cost_str); + upload_menu->getChild<LLView>("Upload Animation")->setLabelArg("[COST]", cost_str); + upload_menu->getChild<LLView>("Bulk Upload")->setLabelArg("[COST]", cost_str); + } + } +} + // List Commands // //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index 69f8a14583..d9ea0da2da 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -139,10 +139,16 @@ protected: BOOL isActionEnabled(const LLSD& command_name); void onCustomAction(const LLSD& command_name); bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept); + /** + * Set upload cost in "Upload" sub menu. + */ + void setUploadCostIfNeeded(); private: LLPanel* mListCommands; LLMenuGL* mMenuGearDefault; LLMenuGL* mMenuAdd; + + bool mNeedUploadCost; // List Commands // //////////////////////////////////////////////////////////////////////////////// }; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index e134840153..e14a5778ad 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -564,6 +564,7 @@ BOOL LLPanelPeople::postBuild() buttonSetAction("chat_btn", boost::bind(&LLPanelPeople::onChatButtonClicked, this)); buttonSetAction("im_btn", boost::bind(&LLPanelPeople::onImButtonClicked, this)); buttonSetAction("call_btn", boost::bind(&LLPanelPeople::onCallButtonClicked, this)); + buttonSetAction("group_call_btn", boost::bind(&LLPanelPeople::onGroupCallButtonClicked, this)); buttonSetAction("teleport_btn", boost::bind(&LLPanelPeople::onTeleportButtonClicked, this)); buttonSetAction("share_btn", boost::bind(&LLPanelPeople::onShareButtonClicked, this)); @@ -573,7 +574,7 @@ BOOL LLPanelPeople::postBuild() getChild<LLPanel>(GROUP_TAB_NAME)->childSetAction("groups_viewsort_btn",boost::bind(&LLPanelPeople::onGroupsViewSortButtonClicked, this)); // Must go after setting commit callback and initializing all pointers to children. - mTabContainer->selectTabByName(FRIENDS_TAB_NAME); + mTabContainer->selectTabByName(NEARBY_TAB_NAME); // Create menus. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -733,6 +734,7 @@ void LLPanelPeople::updateButtons() buttonSetVisible("view_profile_btn", !group_tab_active); buttonSetVisible("im_btn", !group_tab_active); buttonSetVisible("call_btn", !group_tab_active); + buttonSetVisible("group_call_btn", group_tab_active); buttonSetVisible("teleport_btn", friends_tab_active); buttonSetVisible("share_btn", nearby_tab_active || friends_tab_active); @@ -781,6 +783,7 @@ void LLPanelPeople::updateButtons() bool none_group_selected = item_selected && selected_id.isNull(); buttonSetEnabled("group_info_btn", !none_group_selected); + buttonSetEnabled("group_call_btn", !none_group_selected); buttonSetEnabled("chat_btn", !none_group_selected); } @@ -962,6 +965,13 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string) mFilterSubString = search_upper; + //store accordion tabs state before any manipulation with accordion tabs + if(!mFilterSubString.empty()) + { + notifyChildren(LLSD().with("action","store_state")); + } + + // Apply new filter. mNearbyList->setNameFilter(mFilterSubString); mOnlineFriendList->setNameFilter(mFilterSubString); @@ -973,6 +983,12 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string) setAccordionCollapsedByUser("tab_all", false); showFriendsAccordionsIfNeeded(); + + //restore accordion tabs state _after_ all manipulations... + if(mFilterSubString.empty()) + { + notifyChildren(LLSD().with("action","restore_state")); + } } void LLPanelPeople::onTabSelected(const LLSD& param) @@ -981,6 +997,8 @@ void LLPanelPeople::onTabSelected(const LLSD& param) mNearbyListUpdater->setActive(tab_name == NEARBY_TAB_NAME); updateButtons(); + showFriendsAccordionsIfNeeded(); + if (GROUP_TAB_NAME == tab_name) mFilterEditor->setLabel(getString("groups_filter_label")); else @@ -1051,7 +1069,7 @@ bool LLPanelPeople::isItemsFreeOfFriends(const std::vector<LLUUID>& uuids) void LLPanelPeople::onAddFriendWizButtonClicked() { // Show add friend wizard. - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(onAvatarPicked, NULL, FALSE, TRUE); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelPeople::onAvatarPicked, _1, _2), FALSE, TRUE); // Need to disable 'ok' button when friend occurs in selection if (picker) picker->setOkBtnEnableCb(boost::bind(&LLPanelPeople::isItemsFreeOfFriends, this, _1)); LLFloater* root_floater = gFloaterView->getParentFloater(this); @@ -1112,8 +1130,7 @@ void LLPanelPeople::onActivateButtonClicked() // static void LLPanelPeople::onAvatarPicked( const std::vector<std::string>& names, - const std::vector<LLUUID>& ids, - void*) + const std::vector<LLUUID>& ids) { if (!names.empty() && !ids.empty()) LLAvatarActions::requestFriendshipDialog(ids[0], names[0]); @@ -1272,6 +1289,11 @@ void LLPanelPeople::onCallButtonClicked() } } +void LLPanelPeople::onGroupCallButtonClicked() +{ + LLGroupActions::startCall(getCurrentItemID()); +} + void LLPanelPeople::onTeleportButtonClicked() { LLAvatarActions::offerTeleport(getCurrentItemID()); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index f5cdc0935c..da2c0e368c 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -100,6 +100,7 @@ private: void onChatButtonClicked(); void onImButtonClicked(); void onCallButtonClicked(); + void onGroupCallButtonClicked(); void onTeleportButtonClicked(); void onShareButtonClicked(); void onMoreButtonClicked(); @@ -128,8 +129,7 @@ private: // misc callbacks static void onAvatarPicked( const std::vector<std::string>& names, - const std::vector<LLUUID>& ids, - void*); + const std::vector<LLUUID>& ids); void onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LLSD& param, LLAvatarList* avatar_list); diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 0314642d9e..c1c10e6022 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -184,8 +184,6 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) 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(); diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 839452d061..7a4dd3569d 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -284,6 +284,7 @@ void LLPanelPickInfo::setPickName(const std::string& name) void LLPanelPickInfo::setPickDesc(const std::string& desc) { childSetValue(XML_DESC, desc); + updateContentPanelRect(); } void LLPanelPickInfo::setPickLocation(const std::string& location) @@ -291,6 +292,31 @@ void LLPanelPickInfo::setPickLocation(const std::string& location) childSetValue(XML_LOCATION, location); } +void LLPanelPickInfo::updateContentPanelRect() +{ + LLTextBox* desc = getChild<LLTextBox>(XML_DESC); + + S32 text_height = desc->getTextPixelHeight(); + LLRect text_rect = desc->getRect(); + + // let text-box height fit text height + text_rect.set(text_rect.mLeft, text_rect.mTop, text_rect.mRight, text_rect.mTop - text_height); + desc->setRect(text_rect); + desc->reshape(text_rect.getWidth(), text_rect.getHeight()); + // force reflow + desc->setText(desc->getText()); + + // bottom of description text-box will be bottom of content panel + desc->localRectToOtherView(desc->getLocalRect(), &text_rect, getChild<LLView>("profile_scroll")); + + LLPanel* content_panel = getChild<LLPanel>("scroll_content_panel"); + LLRect content_rect = content_panel->getRect(); + content_rect.set(content_rect.mLeft, content_rect.mTop, content_rect.mRight, text_rect.mBottom); + // Somehow setRect moves all elements down. + // Single reshape() updates rect and does not move anything. + content_panel->reshape(content_rect.getWidth(), content_rect.getHeight()); +} + void LLPanelPickInfo::onClickMap() { LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 95add387d0..12b5a116b4 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -140,6 +140,15 @@ protected: virtual LLVector3d& getPosGlobal() { return mPosGlobal; } /** + * Reshapes content panel to fit all elements. + * + * Assume that description text-box is the last element of panel. + * Reshape text-box to fit text height and then reshape content panel to fit + * text-box bottom. EXT-1326 + */ + void updateContentPanelRect(); + + /** * Callback for "Map" button, opens Map */ void onClickMap(); diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 4d22d96072..751705dd57 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -485,6 +485,18 @@ void LLPanelPicks::onOpen(const LLSD& key) LLPanelProfileTab::onOpen(key); } +void LLPanelPicks::onClosePanel() +{ + if (mPanelClassifiedInfo) + { + onPanelClassifiedClose(mPanelClassifiedInfo); + } + if (mPanelPickInfo) + { + onPanelPickClose(mPanelPickInfo); + } +} + void LLPanelPicks::onListCommit(const LLFlatListView* f_list) { // Make sure only one of the lists has selection. @@ -769,6 +781,11 @@ void LLPanelPicks::onPanelPickSave(LLPanel* panel) void LLPanelPicks::onPanelClassifiedSave(LLPanelClassifiedEdit* panel) { + if(!panel->canClose()) + { + return; + } + if(panel->isNew()) { LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), panel->getClassifiedId()); diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index fd8a9e6938..1b2e35ca46 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -74,6 +74,8 @@ public: /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClosePanel(); + void processProperties(void* data, EAvatarProcessorType type); void updateData(); diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 596bd2909a..245f694ac6 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -60,13 +60,18 @@ class LLTeleportHistoryFlatItem : public LLPanel { public: LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string ®ion_name, const std::string &hl); - virtual ~LLTeleportHistoryFlatItem() {}; + virtual ~LLTeleportHistoryFlatItem(); virtual BOOL postBuild(); + /*virtual*/ S32 notify(const LLSD& info); + S32 getIndex() { return mIndex; } void setIndex(S32 index) { mIndex = index; } const std::string& getRegionName() { return mRegionName;} + void setRegionName(const std::string& name); + void setHighlightedText(const std::string& text); + void updateTitle(); /*virtual*/ void setValue(const LLSD& value); @@ -75,18 +80,51 @@ public: virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); static void showPlaceInfoPanel(S32 index); + + LLHandle<LLTeleportHistoryFlatItem> getItemHandle() { mItemHandle.bind(this); return mItemHandle; } + private: void onProfileBtnClick(); LLButton* mProfileBtn; + LLTextBox* mTitle; LLTeleportHistoryPanel::ContextMenu *mContextMenu; S32 mIndex; std::string mRegionName; std::string mHighlight; + LLRootHandle<LLTeleportHistoryFlatItem> mItemHandle; +}; + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage> { +protected: + typedef std::vector< LLHandle<LLTeleportHistoryFlatItem> > flat_item_list_t; + +public: + LLTeleportHistoryFlatItem* getFlatItemForPersistentItem ( + LLTeleportHistoryPanel::ContextMenu *context_menu, + const LLTeleportHistoryPersistentItem& persistent_item, + const S32 cur_item_index, + const std::string &hl); + + void removeItem(LLTeleportHistoryFlatItem* item); + + void purge(); + +private: + + flat_item_list_t mItems; }; +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string ®ion_name, const std::string &hl) : LLPanel(), mIndex(index), @@ -97,18 +135,37 @@ LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistor LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history_item.xml"); } +LLTeleportHistoryFlatItem::~LLTeleportHistoryFlatItem() +{ +} + //virtual BOOL LLTeleportHistoryFlatItem::postBuild() { - LLTextUtil::textboxSetHighlightedVal(getChild<LLTextBox>("region"), LLStyle::Params(), mRegionName, mHighlight); + mTitle = getChild<LLTextBox>("region"); mProfileBtn = getChild<LLButton>("profile_btn"); mProfileBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onProfileBtnClick, this)); + updateTitle(); + return true; } +S32 LLTeleportHistoryFlatItem::notify(const LLSD& info) +{ + if(info.has("detach")) + { + delete mMouseDownSignal; + mMouseDownSignal = NULL; + delete mRightMouseDownSignal; + mRightMouseDownSignal = NULL; + return 1; + } + return 0; +} + void LLTeleportHistoryFlatItem::setValue(const LLSD& value) { if (!value.isMap()) return;; @@ -116,6 +173,25 @@ void LLTeleportHistoryFlatItem::setValue(const LLSD& value) childSetVisible("selected_icon", value["selected"]); } +void LLTeleportHistoryFlatItem::setHighlightedText(const std::string& text) +{ + mHighlight = text; +} + +void LLTeleportHistoryFlatItem::setRegionName(const std::string& name) +{ + mRegionName = name; +} + +void LLTeleportHistoryFlatItem::updateTitle() +{ + LLTextUtil::textboxSetHighlightedVal( + mTitle, + LLStyle::Params(), + mRegionName, + mHighlight); +} + void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask) { childSetVisible("hovered_icon", true); @@ -155,6 +231,82 @@ void LLTeleportHistoryFlatItem::onProfileBtnClick() LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex); } +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +LLTeleportHistoryFlatItem* +LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem ( + LLTeleportHistoryPanel::ContextMenu *context_menu, + const LLTeleportHistoryPersistentItem& persistent_item, + const S32 cur_item_index, + const std::string &hl) +{ + LLTeleportHistoryFlatItem* item = NULL; + if ( cur_item_index < (S32) mItems.size() ) + { + item = mItems[cur_item_index].get(); + if (item->getParent() == NULL) + { + item->setIndex(cur_item_index); + item->setRegionName(persistent_item.mTitle); + item->setHighlightedText(hl); + item->setVisible(TRUE); + item->updateTitle(); + } + else + { + // Item already added to parent + item = NULL; + } + } + + if ( !item ) + { + item = new LLTeleportHistoryFlatItem(cur_item_index, + context_menu, + persistent_item.mTitle, + hl); + mItems.push_back(item->getItemHandle()); + } + + return item; +} + +void LLTeleportHistoryFlatItemStorage::removeItem(LLTeleportHistoryFlatItem* item) +{ + if (item) + { + flat_item_list_t::iterator item_iter = std::find(mItems.begin(), + mItems.end(), + item->getItemHandle()); + if (item_iter != mItems.end()) + { + mItems.erase(item_iter); + } + } +} + +void LLTeleportHistoryFlatItemStorage::purge() +{ + for ( flat_item_list_t::iterator + it = mItems.begin(), + it_end = mItems.end(); + it != it_end; ++it ) + { + LLHandle <LLTeleportHistoryFlatItem> item_handle = *it; + if ( !item_handle.isDead() && item_handle.get()->getParent() == NULL ) + { + item_handle.get()->die(); + } + } + mItems.clear(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + LLTeleportHistoryPanel::ContextMenu::ContextMenu() : mMenu(NULL) { @@ -236,6 +388,7 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel() LLTeleportHistoryPanel::~LLTeleportHistoryPanel() { + LLTeleportHistoryFlatItemStorage::instance().purge(); LLView::deleteViewByHandle(mGearMenuHandle); } @@ -299,6 +452,7 @@ BOOL LLTeleportHistoryPanel::postBuild() registrar.add("TeleportHistory.ExpandAllFolders", boost::bind(&LLTeleportHistoryPanel::onExpandAllFolders, this)); registrar.add("TeleportHistory.CollapseAllFolders", boost::bind(&LLTeleportHistoryPanel::onCollapseAllFolders, this)); registrar.add("TeleportHistory.ClearTeleportHistory", boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistory, this)); + mEnableCallbackRegistrar.add("TeleportHistory.GearMenu.Enable", boost::bind(&LLTeleportHistoryPanel::isActionEnabled, this, _2)); LLMenuGL* gear_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); if(gear_menu) @@ -478,16 +632,15 @@ void LLTeleportHistoryPanel::refresh() while (mCurrentItem >= 0) { // Filtering - std::string landmark_title = items[mCurrentItem].mTitle; - LLStringUtil::toUpper(landmark_title); - - std::string::size_type match_offset = sFilterSubString.size() ? landmark_title.find(sFilterSubString) : std::string::npos; - bool passed = sFilterSubString.size() == 0 || match_offset != std::string::npos; - - if (!passed) + if (!sFilterSubString.empty()) { - mCurrentItem--; - continue; + std::string landmark_title(items[mCurrentItem].mTitle); + LLStringUtil::toUpper(landmark_title); + if( std::string::npos == landmark_title.find(sFilterSubString) ) + { + mCurrentItem--; + continue; + } } // Checking whether date of item is earlier, than tab_boundary_date. @@ -507,6 +660,9 @@ void LLTeleportHistoryPanel::refresh() // Expand all accordion tabs when filtering if(!sFilterSubString.empty()) { + //store accordion tab state when filter is not empty + tab->notifyChildren(LLSD().with("action","store_state")); + tab->setDisplayChildren(true); } // Restore each tab's expand state when not filtering @@ -514,6 +670,9 @@ void LLTeleportHistoryPanel::refresh() { bool collapsed = isAccordionCollapsedByUser(tab); tab->setDisplayChildren(!collapsed); + + //restore accordion state after all those accodrion tabmanipulations + tab->notifyChildren(LLSD().with("action","restore_state")); } curr_flat_view = getFlatListViewFromTab(tab); @@ -521,9 +680,14 @@ void LLTeleportHistoryPanel::refresh() if (curr_flat_view) { - LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle, sFilterSubString); - curr_flat_view->addItem(item); - + LLTeleportHistoryFlatItem* item = + LLTeleportHistoryFlatItemStorage::instance() + .getFlatItemForPersistentItem(&mContextMenu, + items[mCurrentItem], + mCurrentItem, + sFilterSubString); + if ( !curr_flat_view->addItem(item, LLUUID::null, ADD_BOTTOM, false) ) + llerrs << "Couldn't add flat item to teleport history." << llendl; if (mLastSelectedItemIndex == mCurrentItem) curr_flat_view->selectItem(item, true); } @@ -534,6 +698,16 @@ void LLTeleportHistoryPanel::refresh() break; } + for (S32 n = mItemContainers.size() - 1; n >= 0; --n) + { + LLAccordionCtrlTab* tab = mItemContainers.get(n); + LLFlatListView* fv = getFlatListViewFromTab(tab); + if (fv) + { + fv->notify(LLSD().with("rearrange", LLSD())); + } + } + mHistoryAccordion->arrange(); updateVerbs(); @@ -566,11 +740,12 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index) } const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems(); - 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 - sFilterSubString); - // added instead of removed + LLTeleportHistoryFlatItem* item = LLTeleportHistoryFlatItemStorage::instance() + .getFlatItemForPersistentItem(&mContextMenu, + history_items[history_items.size() - 1], // Most recent item, it was added instead of removed + history_items.size(), // index will be decremented inside loop below + sFilterSubString); + fv->addItem(item, LLUUID::null, ADD_TOP); // Index of each item, from last to removed item should be decremented @@ -598,6 +773,8 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index) if (item->getIndex() == removed_index) { + LLTeleportHistoryFlatItemStorage::instance().removeItem(item); + fv->removeItem(item); // If flat list becames empty, then accordion tab should be hidden @@ -629,10 +806,12 @@ void LLTeleportHistoryPanel::showTeleportHistory() LLFlatListView* fv = getFlatListViewFromTab(tab); if (fv) - fv->clear(); + { + // Detached panels are managed by LLTeleportHistoryFlatItemStorage + std::vector<LLPanel*> detached_items; + fv->detachItems(detached_items); + } } - - refresh(); } void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected) @@ -801,6 +980,49 @@ void LLTeleportHistoryPanel::onGearButtonClicked() LLMenuGL::showPopup(this, menu, menu_x, menu_y); } +bool LLTeleportHistoryPanel::isActionEnabled(const LLSD& userdata) const +{ + S32 tabs_cnt = mItemContainers.size(); + + bool has_expanded_tabs = false; + bool has_collapsed_tabs = false; + + for (S32 n = 0; n < tabs_cnt; n++) + { + LLAccordionCtrlTab* tab = mItemContainers.get(n); + if (!tab->getVisible()) + continue; + + if (tab->getDisplayChildren()) + { + has_expanded_tabs = true; + } + else + { + has_collapsed_tabs = true; + } + + if (has_expanded_tabs && has_collapsed_tabs) + { + break; + } + } + + std::string command_name = userdata.asString(); + + if (has_expanded_tabs && command_name == "collapse_all") + { + return true; + } + + if (has_collapsed_tabs && command_name == "expand_all") + { + return true; + } + + return false; +} + void LLTeleportHistoryPanel::setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed) { LLSD param = acc_tab->getValue(); diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h index 0c0f891f32..4eeaec7705 100644 --- a/indra/newview/llpanelteleporthistory.h +++ b/indra/newview/llpanelteleporthistory.h @@ -97,6 +97,7 @@ private: void handleItemSelect(LLFlatListView* ); LLFlatListView* getFlatListViewFromTab(LLAccordionCtrlTab *); void onGearButtonClicked(); + bool isActionEnabled(const LLSD& userdata) const; void setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed); bool isAccordionCollapsedByUser(LLUICtrl* acc_tab); diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index afb9892d12..e2da4c4475 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -36,10 +36,8 @@ #include "lltrans.h" #include "llavataractions.h" #include "llagent.h" -#include "llimview.h" #include "llparticipantlist.h" -#include "llavatarlist.h" #include "llspeakers.h" #include "llviewermenu.h" #include "llvoiceclient.h" @@ -51,12 +49,14 @@ static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR; -LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu/* = true*/): +LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu/* = true*/, + bool exclude_agent /*= true*/): mSpeakerMgr(data_source), mAvatarList(avatar_list), mSortOrder(E_SORT_BY_NAME) , mParticipantListMenu(NULL) -, mExcludeAgent(true) +, mExcludeAgent(exclude_agent) +, mValidateSpeakerCallback(NULL) { mSpeakerAddListener = new SpeakerAddListener(*this); mSpeakerRemoveListener = new SpeakerRemoveListener(*this); @@ -86,23 +86,23 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av } //Lets fill avatarList with existing speakers - LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs(); - LLSpeakerMgr::speaker_list_t speaker_list; mSpeakerMgr->getSpeakerList(&speaker_list, true); 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); + addAvatarIDExceptAgent(speakerp->mID); if ( speakerp->mIsModerator ) { mModeratorList.insert(speakerp->mID); } + else + { + mModeratorToRemoveList.insert(speakerp->mID); + } } // we need to exclude agent id for non group chat - mExcludeAgent = !gAgent.isInGroup(mSpeakerMgr->getSessionID()); - mAvatarList->setDirty(true); sort(); } @@ -162,7 +162,7 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) { std::string name = item->getAvatarName(); size_t found = name.find(moderator_indicator); - if (found == std::string::npos) + if (found != std::string::npos) { name.erase(found, moderator_indicator_len); item->setName(name); @@ -204,42 +204,37 @@ void LLParticipantList::setSortOrder(EParticipantSortOrder order) } } -void LLParticipantList::refreshVoiceState() +LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder() +{ + return mSortOrder; +} + +void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb) { - LLSpeakerMgr::speaker_list_t speakers; - mSpeakerMgr->getSpeakerList(&speakers, TRUE); + mValidateSpeakerCallback = cb; +} - for (LLSpeakerMgr::speaker_list_t::iterator iter = speakers.begin(); - iter != speakers.end(); ++iter) +void LLParticipantList::updateRecentSpeakersOrder() +{ + if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder()) { - 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); - } + // Need to update speakers to sort list correctly + mSpeakerMgr->update(true); + // Resort avatar list + sort(); } } bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) { - LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs(); LLUUID uu_id = event->getValue().asUUID(); - LLAvatarList::uuid_vector_t::iterator found = std::find(group_members.begin(), group_members.end(), uu_id); - if(found != group_members.end()) + if (mValidateSpeakerCallback && !mValidateSpeakerCallback(uu_id)) { - llinfos << "Already got a buddy" << llendl; return true; } - addAvatarIDExceptAgent(group_members, uu_id); - // Mark AvatarList as dirty one - mAvatarList->setDirty(); + addAvatarIDExceptAgent(uu_id); sort(); return true; } @@ -312,7 +307,6 @@ void LLParticipantList::sort() if ( !mAvatarList ) return; - // TODO: Implement more sorting orders after specs updating (EM) switch ( mSortOrder ) { case E_SORT_BY_NAME : // if mExcludeAgent == true , then no need to keep agent on top of the list @@ -326,17 +320,25 @@ void LLParticipantList::sort() mAvatarList->sort(); } break; + case E_SORT_BY_RECENT_SPEAKERS: + if (mSortByRecentSpeakers.isNull()) + mSortByRecentSpeakers = new LLAvatarItemRecentSpeakerComparator(*this); + mAvatarList->setComparator(mSortByRecentSpeakers.get()); + mAvatarList->sort(); + break; default : llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl; return; } } -void LLParticipantList::addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id) +void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) { if (mExcludeAgent && gAgent.getID() == avatar_id) return; + if (mAvatarList->contains(avatar_id)) return; - existing_list.push_back(avatar_id); + mAvatarList->getIDs().push_back(avatar_id); + mAvatarList->setDirty(); adjustParticipant(avatar_id); } @@ -356,7 +358,7 @@ bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::L { /** * 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 + * @see 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); @@ -402,6 +404,7 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + registrar.add("ParticipantList.Sort", boost::bind(&LLParticipantList::LLParticipantListMenu::sortParticipantList, this, _2)); registrar.add("ParticipantList.ToggleAllowTextChat", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleAllowTextChat, this, _2)); registrar.add("ParticipantList.ToggleMuteText", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteText, this, _2)); @@ -447,6 +450,24 @@ void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteSelected", false); LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteOthers", false); } + + // Don't show sort options for P2P chat + bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1); + LLMenuGL::sMenuContainer->childSetVisible("SortByName", is_sort_visible); + LLMenuGL::sMenuContainer->childSetVisible("SortByRecentSpeakers", is_sort_visible); +} + +void LLParticipantList::LLParticipantListMenu::sortParticipantList(const LLSD& userdata) +{ + std::string param = userdata.asString(); + if ("sort_by_name" == param) + { + mParent.setSortOrder(E_SORT_BY_NAME); + } + else if ("sort_by_recent_speakers" == param) + { + mParent.setSortOrder(E_SORT_BY_RECENT_SPEAKERS); + } } void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& userdata) @@ -555,37 +576,50 @@ void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(co bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata) { std::string item = userdata.asString(); - if (item == "can_mute_text") + if (item == "can_mute_text" || "can_block" == item) { return mUUIDs.front() != gAgentID; } - else - if (item == "can_allow_text_chat" || "can_moderate_voice" == item) + else if (item == "can_allow_text_chat") + { + return isGroupModerator(); + } + else if ("can_moderate_voice" == item) + { + if (isGroupModerator()) { - return isGroupModerator(); + LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(mUUIDs.front()); + if (speakerp.notNull()) + { + // not in voice participants can not be moderated + return speakerp->mStatus == LLSpeaker::STATUS_VOICE_ACTIVE + || speakerp->mStatus == LLSpeaker::STATUS_MUTED; + } } + return false; + } else if (item == std::string("can_add")) - { - // We can add friends if: - // - there are selected people - // - and there are no friends among selection yet. + { + // We can add friends if: + // - there are selected people + // - and there are no friends among selection yet. - bool result = (mUUIDs.size() > 0); + bool result = (mUUIDs.size() > 0); - std::vector<LLUUID>::const_iterator - id = mUUIDs.begin(), - uuids_end = mUUIDs.end(); + std::vector<LLUUID>::const_iterator + id = mUUIDs.begin(), + uuids_end = mUUIDs.end(); - for (;id != uuids_end; ++id) + for (;id != uuids_end; ++id) + { + if ( LLAvatarActions::isFriend(*id) ) { - if ( LLAvatarActions::isFriend(*id) ) - { - result = false; - break; - } + result = false; + break; } - return result; } + return result; + } else if (item == "can_call") { return LLVoiceClient::voiceEnabled(); @@ -616,8 +650,45 @@ bool LLParticipantList::LLParticipantListMenu::checkContextMenuItem(const LLSD& { return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat); } + else if(item == "is_sorted_by_name") + { + return E_SORT_BY_NAME == mParent.mSortOrder; + } + else if(item == "is_sorted_by_recent_speakers") + { + return E_SORT_BY_RECENT_SPEAKERS == mParent.mSortOrder; + } return false; } +bool LLParticipantList::LLAvatarItemRecentSpeakerComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const +{ + if (mParent.mSpeakerMgr) + { + LLPointer<LLSpeaker> lhs = mParent.mSpeakerMgr->findSpeaker(avatar_item1->getAvatarId()); + LLPointer<LLSpeaker> rhs = mParent.mSpeakerMgr->findSpeaker(avatar_item2->getAvatarId()); + if ( lhs.notNull() && rhs.notNull() ) + { + // Compare by last speaking time + if( lhs->mLastSpokeTime != rhs->mLastSpokeTime ) + return ( lhs->mLastSpokeTime > rhs->mLastSpokeTime ); + else if ( lhs->mSortIndex != rhs->mSortIndex ) + return ( lhs->mSortIndex < rhs->mSortIndex ); + } + else if ( lhs.notNull() ) + { + // True if only avatar_item1 speaker info available + return true; + } + else if ( rhs.notNull() ) + { + // False if only avatar_item2 speaker info available + return false; + } + } + // By default compare by name. + return LLAvatarItemNameComparator::doCompare(avatar_item1, avatar_item2); +} + //EOF diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 72c413d188..70badbc40d 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -33,7 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llevent.h" #include "llpanelpeoplemenus.h" -#include "llimview.h" +#include "llavatarlist.h" // for LLAvatarItemRecentSpeakerComparator class LLSpeakerMgr; class LLAvatarList; @@ -43,24 +43,44 @@ class LLParticipantList { LOG_CLASS(LLParticipantList); public: - LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true); + + typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t; + + LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true, bool exclude_agent = true); ~LLParticipantList(); void setSpeakingIndicatorsVisible(BOOL visible); typedef enum e_participant_sort_oder { E_SORT_BY_NAME = 0, + E_SORT_BY_RECENT_SPEAKERS = 1, } EParticipantSortOrder; /** + * Adds specified avatar ID to the existing list if it is not Agent's ID + * + * @param[in] avatar_id - Avatar UUID to be added into the list + */ + void addAvatarIDExceptAgent(const LLUUID& avatar_id); + + /** * Set and sort Avatarlist by given order */ void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME); + EParticipantSortOrder getSortOrder(); + + /** + * Refreshes the participant list if it's in sort by recent speaker order. + */ + void updateRecentSpeakersOrder(); /** - * Refreshes participants to display ones not in voice as disabled. - * TODO: mantipov: probably should be moved into derived class for LLFloaterCall + * Set a callback to be called before adding a speaker. Invalid speakers will not be added. + * + * If the callback is unset all speakers are considered as valid. + * + * @see onAddItemEvent() */ - void refreshVoiceState(); + void setValidateSpeakerCallback(validate_speaker_callback_t cb); protected: /** @@ -139,6 +159,7 @@ class LLParticipantList bool enableContextMenuItem(const LLSD& userdata); bool checkContextMenuItem(const LLSD& userdata); + void sortParticipantList(const LLSD& userdata); void toggleAllowTextChat(const LLSD& userdata); void toggleMute(const LLSD& userdata, U32 flags); void toggleMuteText(const LLSD& userdata); @@ -195,19 +216,26 @@ class LLParticipantList void moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute); }; + /** + * Comparator for comparing avatar items by last spoken time + */ + class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator, public LLRefCount + { + LOG_CLASS(LLAvatarItemRecentSpeakerComparator); + public: + LLAvatarItemRecentSpeakerComparator(LLParticipantList& parent):mParent(parent){}; + virtual ~LLAvatarItemRecentSpeakerComparator() {}; + protected: + virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const; + private: + LLParticipantList& mParent; + }; + private: void onAvatarListDoubleClicked(LLAvatarList* list); void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param); /** - * 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. @@ -240,4 +268,7 @@ class LLParticipantList boost::signals2::connection mAvatarListDoubleClickConnection; boost::signals2::connection mAvatarListRefreshConnection; boost::signals2::connection mAvatarListReturnConnection; + + LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers; + validate_speaker_callback_t mValidateSpeakerCallback; }; diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp new file mode 100644 index 0000000000..4de953a59d --- /dev/null +++ b/indra/newview/llplacesinventorypanel.cpp @@ -0,0 +1,191 @@ +/** + * @file llplacesinventorypanel.cpp + * @brief LLPlacesInventoryPanel class definition + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llscrollcontainer.h" + +#include "llplacesinventorypanel.h" + +#include "llfoldervieweventlistener.h" +#include "llinventorybridge.h" +#include "llinventoryfunctions.h" +#include "llpanellandmarks.h" +#include "llplacesinventorybridge.h" + +static LLDefaultChildRegistry::Register<LLPlacesInventoryPanel> r("places_inventory_panel"); + +static const LLPlacesInventoryBridgeBuilder PLACES_INVENTORY_BUILDER; + +LLPlacesInventoryPanel::LLPlacesInventoryPanel(const Params& p) : + LLInventoryPanel(p), + mSavedFolderState(NULL) + +{ + mInvFVBridgeBuilder = &PLACES_INVENTORY_BUILDER; + mSavedFolderState = new LLSaveFolderState(); + mSavedFolderState->setApply(FALSE); +} + + +LLPlacesInventoryPanel::~LLPlacesInventoryPanel() +{ + delete mSavedFolderState; +} + +BOOL LLPlacesInventoryPanel::postBuild() +{ + LLInventoryPanel::postBuild(); + + // clear Contents(); + { + mFolders->destroyView(); + mFolders->getParent()->removeChild(mFolders); + mFolders->die(); + + if( mScroller ) + { + removeChild( mScroller ); + mScroller->die(); + mScroller = NULL; + } + mFolders = NULL; + } + + + mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves + + // create root folder + { + LLRect folder_rect(0, + 0, + getRect().getWidth(), + 0); + LLPlacesFolderView::Params p; + p.name = getName(); + p.rect = folder_rect; + p.parent_panel = this; + mFolders = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p); + mFolders->setAllowMultiSelect(mAllowMultiSelect); + } + + mCommitCallbackRegistrar.popScope(); + + mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); + + // scroller + { + LLRect scroller_view_rect = getRect(); + scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); + LLScrollContainer::Params p; + p.name("Inventory Scroller"); + p.rect(scroller_view_rect); + p.follows.flags(FOLLOWS_ALL); + p.reserve_scroll_corner(true); + p.tab_stop(true); + mScroller = LLUICtrlFactory::create<LLScrollContainer>(p); + } + addChild(mScroller); + mScroller->addChild(mFolders); + + mFolders->setScrollContainer(mScroller); + + + // cut subitems + mFolders->setUseEllipses(true); + + return TRUE; +} + +// save current folder open state +void LLPlacesInventoryPanel::saveFolderState() +{ + mSavedFolderState->setApply(FALSE); + getRootFolder()->applyFunctorRecursively(*mSavedFolderState); +} + +// re-open folders which state was saved +void LLPlacesInventoryPanel::restoreFolderState() +{ + mSavedFolderState->setApply(TRUE); + getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + LLOpenFoldersWithSelection opener; + getRootFolder()->applyFunctorRecursively(opener); + getRootFolder()->scrollToShowSelection(); +} + +/************************************************************************/ +/* PROTECTED METHODS */ +/************************************************************************/ + + + +/************************************************************************/ +/* LLPlacesFolderView implementation */ +/************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS +////////////////////////////////////////////////////////////////////////// + +BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + // let children to change selection first + childrenHandleRightMouseDown(x, y, mask); + mParentLandmarksPanel->setCurrentSelectedList((LLPlacesInventoryPanel*)getParentPanel()); + + // then determine its type and set necessary menu handle + if (getCurSelectedItem()) + { + LLInventoryType::EType inventory_type = getCurSelectedItem()->getListener()->getInventoryType(); + inventory_type_menu_handle_t::iterator it_handle = mMenuHandlesByInventoryType.find(inventory_type); + + if (it_handle != mMenuHandlesByInventoryType.end()) + { + mPopupMenuHandle = (*it_handle).second; + } + else + { + llwarns << "Requested menu handle for non-setup inventory type: " << inventory_type << llendl; + } + + } + + return LLFolderView::handleRightMouseDown(x, y, mask); +} + +void LLPlacesFolderView::setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle) +{ + mMenuHandlesByInventoryType[asset_type] = menu_handle; +} + +// EOF diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h new file mode 100644 index 0000000000..7b34045d32 --- /dev/null +++ b/indra/newview/llplacesinventorypanel.h @@ -0,0 +1,96 @@ +/** + * @file llplacesinventorypanel.h + * @brief LLPlacesInventoryPanel class declaration + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLINVENTORYSUBTREEPANEL_H +#define LL_LLINVENTORYSUBTREEPANEL_H + +#include "llfloaterinventory.h" +#include "llinventorypanel.h" +#include "llfolderview.h" + +class LLLandmarksPanel; + +class LLPlacesInventoryPanel : public LLInventoryPanel +{ +public: + struct Params + : public LLInitParam::Block<Params, LLInventoryPanel::Params> + { + Params() + {} + }; + + LLPlacesInventoryPanel(const Params& p); + ~LLPlacesInventoryPanel(); + + /*virtual*/ BOOL postBuild(); + + void saveFolderState(); + void restoreFolderState(); + +private: + LLSaveFolderState* mSavedFolderState; +}; + + +class LLPlacesFolderView : public LLFolderView +{ +public: + LLPlacesFolderView(const LLFolderView::Params& p) : LLFolderView(p) {}; + /** + * Handles right mouse down + * + * Contains workaround for EXT-2786: sets current selected list for landmark + * panel using @c mParentLandmarksPanel which is set in @c LLLandmarksPanel::initLandmarksPanel + */ + /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + + void setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle); + + void setParentLandmarksPanel(LLLandmarksPanel* panel) + { + mParentLandmarksPanel = panel; + } + + S32 getSelectedCount() { return (S32)mSelectedItems.size(); } + +private: + /** + * holds pointer to landmark panel. This pointer is used in @c LLPlacesFolderView::handleRightMouseDown + */ + LLLandmarksPanel* mParentLandmarksPanel; + typedef std::map<LLInventoryType::EType, LLHandle<LLView> > inventory_type_menu_handle_t; + inventory_type_menu_handle_t mMenuHandlesByInventoryType; + +}; + +#endif //LL_LLINVENTORYSUBTREEPANEL_H diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 26694ac433..a857e30d4f 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -419,12 +419,10 @@ void LLPreviewTexture::updateDimensions() view_height += info_height; S32 button_height = 0; - if (mShowKeepDiscard || mCopyToInv) { //mCopyToInvBtn - - // add space for buttons - view_height += BTN_HEIGHT + CLIENT_RECT_VPAD; - button_height = BTN_HEIGHT + PREVIEW_PAD; - } + + // add space for buttons + view_height += (BTN_HEIGHT + CLIENT_RECT_VPAD) * 3; + button_height = (BTN_HEIGHT + PREVIEW_PAD) * 3; view_width = llmax(view_width, getMinWidth()); view_height = llmax(view_height, getMinHeight()); diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index 5f6b210767..7a48f890e0 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -72,10 +72,12 @@ const S32 ANIMATION_FRAMES = 1; //13; LLProgressView::LLProgressView(const LLRect &rect) : LLPanel(), mPercentDone( 0.f ), - mMouseDownInActiveArea( false ) + mMouseDownInActiveArea( false ), + mUpdateEvents("LLProgressView") { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_progress.xml"); reshape(rect.getWidth(), rect.getHeight()); + mUpdateEvents.listen("self", boost::bind(&LLProgressView::handleUpdate, this, _1)); } BOOL LLProgressView::postBuild() @@ -260,3 +262,26 @@ void LLProgressView::onClickMessage(void* data) } } } + +bool LLProgressView::handleUpdate(const LLSD& event_data) +{ + LLSD message = event_data.get("message"); + LLSD desc = event_data.get("desc"); + LLSD percent = event_data.get("percent"); + + if(message.isDefined()) + { + setMessage(message.asString()); + } + + if(desc.isDefined()) + { + setText(desc.asString()); + } + + if(percent.isDefined()) + { + setPercent(percent.asReal()); + } + return false; +} diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h index 865646c85d..6853674d88 100644 --- a/indra/newview/llprogressview.h +++ b/indra/newview/llprogressview.h @@ -35,6 +35,7 @@ #include "llpanel.h" #include "llframetimer.h" +#include "llevents.h" class LLImageRaw; class LLButton; @@ -75,7 +76,12 @@ protected: LLRect mOutlineRect; bool mMouseDownInActiveArea; + // The LLEventStream mUpdateEvents depends upon this class being a singleton + // to avoid pump name conflicts. static LLProgressView* sInstance; + LLEventStream mUpdateEvents; + + bool handleUpdate(const LLSD& event_data); }; #endif // LL_LLPROGRESSVIEW_H diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index bd256ec9c2..da3f1543dd 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -217,7 +217,10 @@ void LLScreenChannel::addToast(const LLToast::Params& p) ToastElem new_toast_elem(p); + // reset HIDDEN flags for the Overflow Toast mOverflowToastHidden = false; + if(mOverflowToastPanel) + mOverflowToastPanel->setIsHidden(false); new_toast_elem.toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1)); new_toast_elem.toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1)); @@ -231,6 +234,11 @@ void LLScreenChannel::addToast(const LLToast::Params& p) if(show_toast) { mToastList.push_back(new_toast_elem); + if(p.can_be_stored) + { + // store toasts immediately - EXT-3762 + storeToast(new_toast_elem); + } updateShowToastsState(); redrawToasts(); } @@ -303,7 +311,6 @@ void LLScreenChannel::storeToast(ToastElem& toast_elem) if( it != mStoredToastList.end() ) return; - toast_elem.toast->stopTimer(); mStoredToastList.push_back(toast_elem); mOnStoreToast(toast_elem.toast->getPanel(), toast_elem.id); } @@ -340,6 +347,13 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id) mOverflowToastHidden = false; LLToast* toast = (*it).toast; + + if(toast->getVisible()) + { + // toast is already in channel + return; + } + toast->setIsHidden(false); toast->resetTimer(); mToastList.push_back((*it)); @@ -459,7 +473,7 @@ void LLScreenChannel::showToastsBottom() S32 toast_margin = 0; std::vector<ToastElem>::reverse_iterator it; - closeOverflowToastPanel(); + LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get()); for(it = mToastList.rbegin(); it != mToastList.rend(); ++it) { @@ -473,6 +487,16 @@ void LLScreenChannel::showToastsBottom() toast_rect.setOriginAndSize(getRect().mLeft, bottom + toast_margin, toast_rect.getWidth() ,toast_rect.getHeight()); (*it).toast->setRect(toast_rect); + // don't show toasts if there is not enough space + if(floater && floater->overlapsScreenChannel()) + { + LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); + if(toast_rect.mTop + getOverflowToastHeight() + toast_margin > world_rect.mTop) + { + break; + } + } + bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop; if(!stop_showing_toasts) @@ -513,7 +537,11 @@ void LLScreenChannel::showToastsBottom() mHiddenToastsNum++; } createOverflowToast(bottom, gSavedSettings.getS32("NotificationTipToastLifeTime")); - } + } + else + { + closeOverflowToastPanel(); + } } //-------------------------------------------------------------------------- @@ -544,11 +572,14 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer) LLRect toast_rect; LLToast::Params p; p.lifetime_secs = timer; - mOverflowToastPanel = new LLToast(p); + + if(!mOverflowToastPanel) + mOverflowToastPanel = new LLToast(p); if(!mOverflowToastPanel) return; + mOverflowToastPanel->startFading(); mOverflowToastPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::onOverflowToastHide, this)); LLTextBox* text_box = mOverflowToastPanel->getChild<LLTextBox>("toast_text"); @@ -567,6 +598,18 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer) toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight()); mOverflowToastPanel->setRect(toast_rect); + // don't show overflow toast if there is not enough space for it. + LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get()); + if(floater && floater->overlapsScreenChannel()) + { + LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); + if(toast_rect.mTop > world_rect.mTop) + { + closeOverflowToastPanel(); + return; + } + } + text_box->setValue(text); text_box->setVisible(TRUE); @@ -606,8 +649,8 @@ void LLScreenChannel::closeOverflowToastPanel() { if(mOverflowToastPanel != NULL) { - mOverflowToastPanel->closeFloater(); - mOverflowToastPanel = NULL; + mOverflowToastPanel->setVisible(FALSE); + mOverflowToastPanel->stopFading(); } } @@ -656,6 +699,24 @@ F32 LLScreenChannel::getHeightRatio() return ratio; } +S32 LLScreenChannel::getOverflowToastHeight() +{ + if(mOverflowToastPanel) + { + return mOverflowToastPanel->getRect().getHeight(); + } + + static S32 height = 0; + if(0 == height) + { + LLToast::Params p; + LLToast* toast = new LLToast(p); + height = toast->getRect().getHeight(); + delete toast; + } + return height; +} + //-------------------------------------------------------------------------- void LLScreenChannel::updateStartUpString(S32 num) { @@ -814,25 +875,22 @@ void LLScreenChannel::updateShowToastsState() return; } - // for Message Well floater showed in a docked state - adjust channel's height - 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(); + + // adjust channel's height + if(floater->overlapsScreenChannel()) { - S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");; - LLRect this_rect = getRect(); - if(floater->getVisible() && floater->isDocked()) + channel_bottom += floater->getRect().getHeight(); + if(floater->getDockControl()) { - channel_bottom += floater->getRect().getHeight(); - if(floater->getDockControl()) - { - channel_bottom += floater->getDockControl()->getTongueHeight(); - } + channel_bottom += floater->getDockControl()->getTongueHeight(); } + } - if(channel_bottom != this_rect.mBottom) - { - setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom)); - } + if(channel_bottom != this_rect.mBottom) + { + setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom)); } } diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 321fb244a1..38f27f756b 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -281,6 +281,8 @@ private: */ static F32 getHeightRatio(); + S32 getOverflowToastHeight(); + // Channel's flags static bool mWasStartUpToastShown; diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 1962d871a6..cf62d47362 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -67,6 +67,7 @@ LLScriptFloater::LLScriptFloater(const LLSD& key) , mScriptForm(NULL) { setMouseDownCallback(boost::bind(&LLScriptFloater::onMouseDown, this)); + setOverlapsScreenChannel(true); } bool LLScriptFloater::toggle(const LLUUID& object_id) diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 30b0075c4b..e2ce534c4f 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -198,7 +198,7 @@ void LLSidepanelAppearance::onFilterEdit(const std::string& search_string) void LLSidepanelAppearance::onOpenOutfitButtonClicked() { - const LLViewerInventoryItem *outfit_link = LLAppearanceManager::getInstance()->getCurrentOutfitLink(); + const LLViewerInventoryItem *outfit_link = LLAppearanceManager::getInstance()->getBaseOutfitLink(); if (!outfit_link) return; if (!outfit_link->getIsLinkType()) @@ -313,7 +313,7 @@ void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name) { if (name == "") { - const LLViewerInventoryItem *outfit_link = LLAppearanceManager::getInstance()->getCurrentOutfitLink(); + const LLViewerInventoryItem *outfit_link = LLAppearanceManager::getInstance()->getBaseOutfitLink(); if (outfit_link) { const LLViewerInventoryCategory *cat = outfit_link->getLinkedCategory(); diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp index 1965e634b6..94fe95d215 100644 --- a/indra/newview/llsidepaneliteminfo.cpp +++ b/indra/newview/llsidepaneliteminfo.cpp @@ -157,22 +157,22 @@ void LLSidepanelItemInfo::reset() void LLSidepanelItemInfo::refresh() { - LLInventoryItem* item = findItem(); + LLViewerInventoryItem* item = findItem(); if(item) { refreshFromItem(item); updateVerbs(); + return; } else { if (getIsEditing()) { setIsEditing(FALSE); - return; } } - if (!getIsEditing() || !item) + if (!getIsEditing()) { const std::string no_item_names[]={ "LabelItemName", @@ -225,24 +225,26 @@ void LLSidepanelItemInfo::refresh() updateVerbs(); } -void LLSidepanelItemInfo::refreshFromItem(LLInventoryItem* item) +void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item) { //////////////////////// // PERMISSIONS LOOKUP // //////////////////////// // do not enable the UI for incomplete items. - LLViewerInventoryItem* i = (LLViewerInventoryItem*)item; - BOOL is_complete = i->isComplete(); - const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(i->getInventoryType()); - const BOOL is_calling_card = (i->getInventoryType() == LLInventoryType::IT_CALLINGCARD); + BOOL is_complete = item->isComplete(); + const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(item->getInventoryType()); + const BOOL is_calling_card = (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD); const LLPermissions& perm = item->getPermissions(); const BOOL can_agent_manipulate = gAgent.allowOperation(PERM_OWNER, perm, GP_OBJECT_MANIPULATE); const BOOL can_agent_sell = gAgent.allowOperation(PERM_OWNER, perm, GP_OBJECT_SET_SALE) && !cannot_restrict_permissions; - const BOOL is_link = i->getIsLinkType(); + const BOOL is_link = item->getIsLinkType(); + + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + bool not_in_trash = item && (item->getUUID() != trash_id) && !gInventory.isObjectDescendentOf(item->getUUID(), trash_id); // You need permission to modify the object to modify an inventory // item in it. @@ -259,7 +261,7 @@ void LLSidepanelItemInfo::refreshFromItem(LLInventoryItem* item) ////////////////////// BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, perm, GP_OBJECT_MANIPULATE) - && is_obj_modify && is_complete; + && is_obj_modify && is_complete && not_in_trash; childSetEnabled("LabelItemNameTitle",TRUE); childSetEnabled("LabelItemName",is_modifiable && !is_calling_card); // for now, don't allow rename of calling cards @@ -336,6 +338,64 @@ void LLSidepanelItemInfo::refreshFromItem(LLInventoryItem* item) LLStringUtil::format (timeStr, substitution); childSetText ("LabelAcquiredDate", timeStr); } + + ///////////////////////////////////// + // PERMISSIONS AND SALE ITEM HIDING + ///////////////////////////////////// + + const std::string perm_and_sale_items[]={ + "perms_inv", + "OwnerLabel", + "perm_modify", + "CheckOwnerModify", + "CheckOwnerCopy", + "CheckOwnerTransfer", + "GroupLabel", + "CheckShareWithGroup", + "AnyoneLabel", + "CheckEveryoneCopy", + "NextOwnerLabel", + "CheckNextOwnerModify", + "CheckNextOwnerCopy", + "CheckNextOwnerTransfer", + "CheckPurchase", + "SaleLabel", + "RadioSaleType", + "combobox sale copy", + "Edit Cost", + "TextPrice" + }; + + const std::string debug_items[]={ + "BaseMaskDebug", + "OwnerMaskDebug", + "GroupMaskDebug", + "EveryoneMaskDebug", + "NextMaskDebug" + }; + + // Hide permissions checkboxes and labels and for sale info if in the trash + // or ui elements don't apply to these objects and return from function + if (!not_in_trash || cannot_restrict_permissions) + { + for(size_t t=0; t<LL_ARRAY_SIZE(perm_and_sale_items); ++t) + { + childSetVisible(perm_and_sale_items[t],false); + } + + for(size_t t=0; t<LL_ARRAY_SIZE(debug_items); ++t) + { + childSetVisible(debug_items[t],false); + } + return; + } + else // Make sure perms and sale ui elements are visible + { + for(size_t t=0; t<LL_ARRAY_SIZE(perm_and_sale_items); ++t) + { + childSetVisible(perm_and_sale_items[t],true); + } + } /////////////////////// // OWNER PERMISSIONS // @@ -539,7 +599,7 @@ void LLSidepanelItemInfo::refreshFromItem(LLInventoryItem* item) void LLSidepanelItemInfo::onClickCreator() { - LLInventoryItem* item = findItem(); + LLViewerInventoryItem* item = findItem(); if(!item) return; if(!item->getCreatorUUID().isNull()) { @@ -550,7 +610,7 @@ void LLSidepanelItemInfo::onClickCreator() // static void LLSidepanelItemInfo::onClickOwner() { - LLInventoryItem* item = findItem(); + LLViewerInventoryItem* item = findItem(); if(!item) return; if(item->getPermissions().isGroupOwned()) { @@ -566,7 +626,7 @@ void LLSidepanelItemInfo::onClickOwner() void LLSidepanelItemInfo::onCommitName() { //llinfos << "LLSidepanelItemInfo::onCommitName()" << llendl; - LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem(); + LLViewerInventoryItem* item = findItem(); if(!item) { return; @@ -602,7 +662,7 @@ void LLSidepanelItemInfo::onCommitName() void LLSidepanelItemInfo::onCommitDescription() { //llinfos << "LLSidepanelItemInfo::onCommitDescription()" << llendl; - LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem(); + LLViewerInventoryItem* item = findItem(); if(!item) return; LLLineEditor* labelItemDesc = getChild<LLLineEditor>("LabelItemDesc"); @@ -640,7 +700,7 @@ void LLSidepanelItemInfo::onCommitDescription() void LLSidepanelItemInfo::onCommitPermissions() { //llinfos << "LLSidepanelItemInfo::onCommitPermissions()" << llendl; - LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem(); + LLViewerInventoryItem* item = findItem(); if(!item) return; LLPermissions perm(item->getPermissions()); @@ -749,7 +809,7 @@ void LLSidepanelItemInfo::onCommitSaleType() void LLSidepanelItemInfo::updateSaleInfo() { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem(); + LLViewerInventoryItem* item = findItem(); if(!item) return; LLSaleInfo sale_info(item->getSaleInfo()); if(!gAgent.allowOperation(PERM_TRANSFER, item->getPermissions(), GP_OBJECT_SET_SALE)) @@ -849,9 +909,9 @@ void LLSidepanelItemInfo::updateSaleInfo() } } -LLInventoryItem* LLSidepanelItemInfo::findItem() const +LLViewerInventoryItem* LLSidepanelItemInfo::findItem() const { - LLInventoryItem* item = NULL; + LLViewerInventoryItem* item = NULL; if(mObjectID.isNull()) { // it is in agent inventory @@ -862,7 +922,7 @@ LLInventoryItem* LLSidepanelItemInfo::findItem() const LLViewerObject* object = gObjectList.findObject(mObjectID); if(object) { - item = (LLInventoryItem*)object->getInventoryObject(mItemID); + item = static_cast<LLViewerInventoryItem*>(object->getInventoryObject(mItemID)); } } return item; diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h index 21002327bc..e6dbf400ee 100644 --- a/indra/newview/llsidepaneliteminfo.h +++ b/indra/newview/llsidepaneliteminfo.h @@ -41,7 +41,7 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLButton; -class LLInventoryItem; +class LLViewerInventoryItem; class LLItemPropertiesObserver; class LLViewerObject; class LLPermissions; @@ -63,10 +63,10 @@ protected: /*virtual*/ void refresh(); /*virtual*/ void save(); - LLInventoryItem* findItem() const; + LLViewerInventoryItem* findItem() const; LLViewerObject* findObject() const; - void refreshFromItem(LLInventoryItem* item); + void refreshFromItem(LLViewerInventoryItem* item); private: LLUUID mItemID; // inventory UUID for the inventory item. diff --git a/indra/newview/llsidetraypanelcontainer.cpp b/indra/newview/llsidetraypanelcontainer.cpp index 3024492ab9..f2215a2250 100644 --- a/indra/newview/llsidetraypanelcontainer.cpp +++ b/indra/newview/llsidetraypanelcontainer.cpp @@ -38,6 +38,7 @@ static LLDefaultChildRegistry::Register<LLSideTrayPanelContainer> r2("panel_cont std::string LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME = "sub_panel_name"; LLSideTrayPanelContainer::Params::Params() + : default_panel_name("default_panel_name") { // Always hide tabs. hide_tabs(true); @@ -45,6 +46,7 @@ LLSideTrayPanelContainer::Params::Params() LLSideTrayPanelContainer::LLSideTrayPanelContainer(const Params& p) : LLTabContainer(p) + , mDefaultPanelName(p.default_panel_name) { } @@ -53,19 +55,14 @@ void LLSideTrayPanelContainer::onOpen(const LLSD& key) // Select specified panel and save navigation history. if(key.has(PARAM_SUB_PANEL_NAME)) { + //*NOTE dzaporozhan + // Navigation history is not used after fix for EXT-3186, + // openPreviousPanel() always opens default panel + // Save panel navigation history std::string panel_name = key[PARAM_SUB_PANEL_NAME]; - S32 old_index = getCurrentPanelIndex(); selectTabByName(panel_name); - - S32 new_index = getCurrentPanelIndex(); - - // Don't update navigation history if we are opening same panel again. - if(old_index != new_index) - { - mPanelHistory[panel_name] = old_index; - } } // Will reopen current panel if no panel name was passed. getCurrentPanel()->onOpen(key); @@ -73,11 +70,13 @@ void LLSideTrayPanelContainer::onOpen(const LLSD& key) void LLSideTrayPanelContainer::openPreviousPanel() { - std::string current_panel_name = getCurrentPanel()->getName(); - panel_navigation_history_t::const_iterator it = mPanelHistory.find(current_panel_name); - if(mPanelHistory.end() != it) + if(!mDefaultPanelName.empty()) + { + selectTabByName(mDefaultPanelName); + } + else { - selectTab(it->second); + selectTab(0); } } diff --git a/indra/newview/llsidetraypanelcontainer.h b/indra/newview/llsidetraypanelcontainer.h index 3f3cb552f8..beed328269 100644 --- a/indra/newview/llsidetraypanelcontainer.h +++ b/indra/newview/llsidetraypanelcontainer.h @@ -51,6 +51,7 @@ public: struct Params : public LLInitParam::Block<Params, LLTabContainer::Params> { + Optional<std::string> default_panel_name; Params(); }; @@ -90,6 +91,7 @@ protected: // Navigation history panel_navigation_history_t mPanelHistory; + std::string mDefaultPanelName; }; #endif //LL_LLSIDETRAY_PANEL_CONTAINER_H diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp index fd39bde118..8f2c877c7a 100644 --- a/indra/newview/llspeakbutton.cpp +++ b/indra/newview/llspeakbutton.cpp @@ -61,7 +61,9 @@ void LLSpeakButton::draw() { // gVoiceClient is the authoritative global source of info regarding our open-mic state, we merely reflect that state. bool openmic = gVoiceClient->getUserPTTState(); - mSpeakBtn->setToggleState(openmic); + bool voiceenabled = gVoiceClient->voiceEnabled(); + mSpeakBtn->setToggleState(openmic && voiceenabled); + mOutputMonitor->setIsMuted(!voiceenabled); LLUICtrl::draw(); } @@ -121,7 +123,7 @@ LLSpeakButton::LLSpeakButton(const Params& p) mOutputMonitor->setIsAgentControl(true); //*TODO find a better place to do that - LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1)); + LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1), true); } LLSpeakButton::~LLSpeakButton() diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 3861a96355..010dfd1b33 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -615,6 +615,9 @@ private: void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) { + LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id); + if (!speakerp) return; + std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); LLSD data; data["method"] = "mute update"; @@ -623,15 +626,13 @@ void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) data["params"]["agent_id"] = speaker_id; data["params"]["mute_info"] = LLSD::emptyMap(); //current value represents ability to type, so invert - data["params"]["mute_info"]["text"] = !findSpeaker(speaker_id)->mModeratorMutedText; + data["params"]["mute_info"]["text"] = !speakerp->mModeratorMutedText; LLHTTPClient::post(url, data, new ModerationResponder(getSessionID())); } void LLIMSpeakerMgr::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute) { - if (gAgentID == avatar_id) return; // do not process myself - LLPointer<LLSpeaker> speakerp = findSpeaker(avatar_id); if (!speakerp) return; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 73e7d99815..99fa271b78 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1082,6 +1082,17 @@ bool idle_startup() credentials["passwd"] = gPassword; login->connect(credentials); + LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK ); + return FALSE; + } + + if(STATE_LOGIN_CURL_UNSTUCK == LLStartUp::getStartupState()) + { + // If we get here we have gotten past the potential stall + // in curl, so take "may appear frozen" out of progress bar. JC + auth_desc = LLTrans::getString("LoginInProgressNoFrozen"); + set_startup_status(progress, auth_desc, auth_message); + LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE ); return FALSE; } @@ -1168,16 +1179,6 @@ bool idle_startup() show_connect_box = true; } } - else - { - // Still waiting for response. - // *TODO:Mani - Actually check for login progress. - // If we get here we have gotten past the potential stall - // in curl, so take "may appear frozen" out of progress bar. JC - auth_desc = LLTrans::getString("LoginInProgressNoFrozen"); - set_startup_status(progress, auth_desc, auth_message); - } - return FALSE; } @@ -1308,6 +1309,7 @@ bool idle_startup() // Move the progress view in front of the UI gViewerWindow->moveProgressViewToFront(); + // direct logging to the debug console's line buffer LLError::logToFixedBuffer(gDebugView->mDebugConsolep); // set initial visibility of debug console @@ -2703,6 +2705,7 @@ std::string LLStartUp::startupStateToString(EStartupState state) RTNENUM( STATE_LOGIN_WAIT ); RTNENUM( STATE_LOGIN_CLEANUP ); RTNENUM( STATE_LOGIN_AUTH_INIT ); + RTNENUM( STATE_LOGIN_CURL_UNSTUCK ); RTNENUM( STATE_LOGIN_PROCESS_RESPONSE ); RTNENUM( STATE_WORLD_INIT ); RTNENUM( STATE_MULTIMEDIA_INIT ); diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index ab11b42e74..92fe9521d3 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -55,6 +55,7 @@ typedef enum { STATE_LOGIN_WAIT, // Wait for user input at login screen STATE_LOGIN_CLEANUP, // Get rid of login screen and start login STATE_LOGIN_AUTH_INIT, // Start login to SL servers + STATE_LOGIN_CURL_UNSTUCK, // Update progress to remove "SL appears frozen" msg. STATE_LOGIN_PROCESS_RESPONSE, // Check authentication reply STATE_WORLD_INIT, // Start building the world STATE_MULTIMEDIA_INIT, // Init the rest of multimedia library diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 9e72464237..5ce3bbb9f6 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 "llimview.h" #include "llsd.h" #include "lltextbox.h" #include "llui.h" @@ -160,6 +159,7 @@ LLStatusBar::LLStatusBar(const LLRect& rect) mBtnVolume = getChild<LLButton>( "volume_btn" ); mBtnVolume->setClickedCallback( onClickVolume, this ); mBtnVolume->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterVolume, this)); + mBtnVolume->setIsChrome(TRUE); gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&LLStatusBar::onVolumeChanged, this, _2)); @@ -225,14 +225,6 @@ LLStatusBar::~LLStatusBar() void LLStatusBar::draw() { refresh(); - - if (isBackgroundVisible()) - { - static LLUICachedControl<S32> drop_shadow_floater ("DropShadowFloater", 0); - static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow"); - gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0, - color_drop_shadow, drop_shadow_floater ); - } LLPanel::draw(); } diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 26f9824f9c..a46ca1f8ac 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -52,7 +52,7 @@ #include "llspeakers.h" //--------------------------------------------------------------------------------- -LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key), +LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLTransientDockableFloater(NULL, true, key), mChannel(NULL), mMessageList(NULL), mSysWellChiclet(NULL), @@ -63,6 +63,7 @@ LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key) { mTypedItemsCount[IT_NOTIFICATION] = 0; mTypedItemsCount[IT_INSTANT_MESSAGE] = 0; + setOverlapsScreenChannel(true); } //--------------------------------------------------------------------------------- @@ -89,13 +90,13 @@ BOOL LLSysWellWindow::postBuild() // mouse up callback is not called in this case. setMouseDownCallback(boost::bind(&LLSysWellWindow::releaseNewMessagesState, this)); - return LLDockableFloater::postBuild(); + return LLTransientDockableFloater::postBuild(); } //--------------------------------------------------------------------------------- void LLSysWellWindow::setMinimized(BOOL minimize) { - LLDockableFloater::setMinimized(minimize); + LLTransientDockableFloater::setMinimized(minimize); } //--------------------------------------------------------------------------------- @@ -105,15 +106,15 @@ void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask) setVisible(TRUE); } -//--------------------------------------------------------------------------------- -LLSysWellWindow::~LLSysWellWindow() -{ +void LLSysWellWindow::setSysWellChiclet(LLSysWellChiclet* chiclet) +{ + mSysWellChiclet = chiclet; + if(mSysWellChiclet) + mSysWellChiclet->updateWidget(isWindowEmpty()); } - //--------------------------------------------------------------------------------- -void LLSysWellWindow::clear() +LLSysWellWindow::~LLSysWellWindow() { - mMessageList->clear(); } //--------------------------------------------------------------------------------- @@ -175,7 +176,7 @@ void LLSysWellWindow::setVisible(BOOL visible) // do not show empty window if (NULL == mMessageList || isWindowEmpty()) visible = FALSE; - LLDockableFloater::setVisible(visible); + LLTransientDockableFloater::setVisible(visible); // update notification channel state if(mChannel) @@ -191,15 +192,9 @@ void LLSysWellWindow::setVisible(BOOL visible) } //--------------------------------------------------------------------------------- -void LLSysWellWindow::onFocusLost() -{ - setVisible(false); -} - -//--------------------------------------------------------------------------------- void LLSysWellWindow::setDocked(bool docked, bool pop_on_undock) { - LLDockableFloater::setDocked(docked, pop_on_undock); + LLTransientDockableFloater::setDocked(docked, pop_on_undock); // update notification channel state if(mChannel) @@ -286,6 +281,7 @@ void LLSysWellWindow::handleItemAdded(EItemType added_item_type) setResizeLimits(min_width,min_height); } + mSysWellChiclet->updateWidget(isWindowEmpty()); } void LLSysWellWindow::handleItemRemoved(EItemType removed_item_type) @@ -299,6 +295,7 @@ void LLSysWellWindow::handleItemRemoved(EItemType removed_item_type) // refresh list to recalculate mSeparator position mMessageList->reshape(mMessageList->getRect().getWidth(), mMessageList->getRect().getHeight()); } + mSysWellChiclet->updateWidget(isWindowEmpty()); } bool LLSysWellWindow::anotherTypeExists(EItemType item_type) @@ -352,6 +349,7 @@ LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& } // Initialize chiclet. + mChiclet->setRect(LLRect(5, 28, 30, 3)); // *HACK: workaround for (EXT-3599) mChiclet->setChicletSizeChangedCallback(boost::bind(&LLIMWellWindow::RowPanel::onChicletSizeChanged, this, mChiclet, _2)); mChiclet->enableCounterControl(true); mChiclet->setCounter(chicletCounter); @@ -742,12 +740,13 @@ BOOL LLIMWellWindow::postBuild() void LLIMWellWindow::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - if (mMessageList->getItemByValue(session_id)) return; + LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); + if (!session) return; - // For im sessions started as voice call chiclet gets created on the first incoming message - if (gIMMgr->isVoiceCall(session_id)) return; + // no need to spawn chiclets for participants in P2P calls called through Avaline + if (session->isP2P() && session->isOtherParticipantAvaline()) return; - if (!gIMMgr->hasSession(session_id)) return; + if (mMessageList->getItemByValue(session_id)) return; addIMRow(session_id, 0, name, other_participant_id); reshapeWindow(); @@ -905,23 +904,6 @@ bool LLIMWellWindow::hasIMRow(const LLUUID& session_id) return mMessageList->getItemByValue(session_id); } -void LLIMWellWindow::onNewIM(const LLSD& data) -{ - LLUUID from_id = data["from_id"]; - if (from_id.isNull() || gAgentID == from_id) return; - - LLUUID session_id = data["session_id"]; - if (session_id.isNull()) return; - - if (!gIMMgr->isVoiceCall(session_id)) return; - - if (hasIMRow(session_id)) return; - - //first real message, time to create chiclet - addIMRow(session_id); -} - - void LLIMWellWindow::closeAll() { // Generate an ignorable alert dialog if there is an active voice IM sesion diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 6cfa25b84d..833e4dd504 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -35,7 +35,7 @@ #include "llsyswellitem.h" -#include "lldockablefloater.h" +#include "lltransientdockablefloater.h" #include "llbutton.h" #include "llscreenchannel.h" #include "llscrollcontainer.h" @@ -50,7 +50,7 @@ class LLScriptChiclet; class LLSysWellChiclet; -class LLSysWellWindow : public LLDockableFloater +class LLSysWellWindow : public LLTransientDockableFloater { public: LLSysWellWindow(const LLSD& key); @@ -62,7 +62,6 @@ public: bool isWindowEmpty(); // Operating with items - void clear( void ); void removeItemByID(const LLUUID& id); // Operating with outfit @@ -72,14 +71,9 @@ public: // override LLFloater's minimization according to EXT-1216 /*virtual*/ void setMinimized(BOOL minimize); - /** - * Hides window when user clicks away from it (EXT-3084) - */ - /*virtual*/ void onFocusLost(); - void onStartUpToastClick(S32 x, S32 y, MASK mask); - void setSysWellChiclet(LLSysWellChiclet* chiclet) { mSysWellChiclet = chiclet; } + void setSysWellChiclet(LLSysWellChiclet* chiclet); // size constants for the window and for its elements static const S32 MAX_WINDOW_HEIGHT = 200; @@ -191,8 +185,6 @@ public: /*virtual*/ void sessionRemoved(const LLUUID& session_id); /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); - void onNewIM(const LLSD& data); - void addObjectRow(const LLUUID& object_id, bool new_message = false); void removeObjectRow(const LLUUID& object_id); diff --git a/indra/newview/llteleporthistory.cpp b/indra/newview/llteleporthistory.cpp index 1315887c37..ce00dec802 100644 --- a/indra/newview/llteleporthistory.cpp +++ b/indra/newview/llteleporthistory.cpp @@ -39,7 +39,6 @@ #include "llagent.h" #include "llslurl.h" -#include "llurlsimstring.h" #include "llviewercontrol.h" // for gSavedSettings #include "llviewerparcelmgr.h" #include "llviewerregion.h" diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 845e71378a..051c189013 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -934,6 +934,8 @@ void LLTextureCache::setDirNames(ELLPath location) void LLTextureCache::purgeCache(ELLPath location) { + LLMutexLock lock(&mHeaderMutex); + if (!mReadOnly) { setDirNames(location); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 5f7c2f5080..25e5e23e6f 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -1237,6 +1237,7 @@ void LLTextureCtrl::draw() // Using the discard level, do not show the string if the texture is almost but not // fully loaded. if ( mTexturep.notNull() && + (!mTexturep->isFullyLoaded()) && (mShowLoadingPlaceholder == TRUE) && (mTexturep->getDiscardLevel() != 1) && (mTexturep->getDiscardLevel() != 0)) diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 0b232da62b..fb1d591e32 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -45,7 +45,7 @@ class LLButton; class LLFloaterTexturePicker; class LLInventoryItem; -class LLViewerTexture; +class LLViewerFetchedTexture; // used for setting drag & drop callbacks. typedef boost::function<BOOL (LLUICtrl*, LLInventoryItem*)> drag_n_drop_callback; @@ -189,7 +189,7 @@ private: drag_n_drop_callback mDropCallback; commit_callback_t mOnCancelCallback; commit_callback_t mOnSelectCallback; - LLPointer<LLViewerTexture> mTexturep; + LLPointer<LLViewerFetchedTexture> mTexturep; LLUIColor mBorderColor; LLUUID mImageItemID; LLUUID mImageAssetID; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 83e0b53960..eeedf38543 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -158,7 +158,7 @@ public: void callbackHttpGet(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer, - bool last_block, bool success); + bool partial, bool success); void callbackCacheRead(bool success, LLImageFormatted* image, S32 imagesize, BOOL islocal); void callbackCacheWrite(bool success); @@ -316,7 +316,7 @@ public: if (HTTP_OK <= status && status < HTTP_MULTIPLE_CHOICES) { success = true; - if (HTTP_PARTIAL_CONTENT == status) // partial information (i.e. last block) + if (HTTP_PARTIAL_CONTENT == status) // partial information { partial = true; } @@ -801,7 +801,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == SEND_HTTP_REQ) { { - const S32 HTTP_QUEUE_MAX_SIZE = 32; + const S32 HTTP_QUEUE_MAX_SIZE = 8; // *TODO: Integrate this with llviewerthrottle // Note: LLViewerThrottle uses dynamic throttling which makes sense for UDP, // but probably not for Textures. @@ -842,10 +842,10 @@ bool LLTextureFetchWorker::doWork(S32 param) mLoaded = FALSE; mGetStatus = 0; mGetReason.clear(); - lldebugs << "HTTP GET: " << mID << " Offset: " << offset - << " Bytes: " << mRequestedSize - << " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << max_bandwidth - << llendl; + LL_DEBUGS("Texture") << "HTTP GET: " << mID << " Offset: " << offset + << " Bytes: " << mRequestedSize + << " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << max_bandwidth + << LL_ENDL; setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); mState = WAIT_HTTP_REQ; @@ -874,16 +874,44 @@ bool LLTextureFetchWorker::doWork(S32 param) S32 cur_size = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0; if (mRequestedSize < 0) { - const S32 HTTP_MAX_RETRY_COUNT = 3; - S32 max_attempts = (mGetStatus == HTTP_NOT_FOUND) ? 1 : HTTP_MAX_RETRY_COUNT + 1; - llinfos << "HTTP GET failed for: " << mUrl - << " Status: " << mGetStatus << " Reason: '" << mGetReason << "'" - << " Attempt:" << mHTTPFailCount+1 << "/" << max_attempts << llendl; - ++mHTTPFailCount; + S32 max_attempts; + if (mGetStatus == HTTP_NOT_FOUND) + { + mHTTPFailCount = max_attempts = 1; // Don't retry + llinfos << "Texture missing from server (404): " << mUrl << llendl; + } + else if (mGetStatus == HTTP_SERVICE_UNAVAILABLE) + { + // *TODO: Should probably introduce a timer here to delay future HTTP requsts + // for a short time (~1s) to ease server load? Ideally the server would queue + // requests instead of returning 503... we already limit the number pending. + ++mHTTPFailCount; + max_attempts = mHTTPFailCount+1; // Keep retrying + LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL; + } + else + { + const S32 HTTP_MAX_RETRY_COUNT = 3; + max_attempts = HTTP_MAX_RETRY_COUNT + 1; + ++mHTTPFailCount; + llinfos << "HTTP GET failed for: " << mUrl + << " Status: " << mGetStatus << " Reason: '" << mGetReason << "'" + << " Attempt:" << mHTTPFailCount+1 << "/" << max_attempts << llendl; + } if (mHTTPFailCount >= max_attempts) { - resetFormattedData(); - return true; // failed + if (cur_size > 0) + { + // Use available data + mLoadedDiscard = mFormattedImage->getDiscardLevel(); + mState = DECODE_IMAGE; + return false; + } + else + { + resetFormattedData(); + return true; // failed + } } else { @@ -934,6 +962,15 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == DECODE_IMAGE) { + static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); + if(textures_decode_disabled) + { + // for debug use, don't decode + mState = DONE; + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + return true; + } + if (mDesiredDiscard < 0) { // We aborted, don't decode @@ -1207,7 +1244,7 @@ bool LLTextureFetchWorker::processSimulatorPackets() void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer, - bool last_block, bool success) + bool partial, bool success) { LLMutexLock lock(&mWorkMutex); @@ -1229,14 +1266,14 @@ void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, gTextureList.sTextureBits += data_size * 8; // Approximate - does not include header bits - //llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl; + LL_DEBUGS("Texture") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL; if (data_size > 0) { // *TODO: set the formatted image data here directly to avoid the copy mBuffer = new U8[data_size]; buffer->readAfter(channels.in(), NULL, mBuffer, data_size); mBufferSize += data_size; - if (data_size < mRequestedSize || last_block == true) + if (data_size < mRequestedSize && mRequestedDiscard == 0) { mHaveAllData = TRUE; } @@ -1422,8 +1459,9 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C)) { // Only do partial requests for J2C at the moment - //llinfos << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << llendl; + //llinfos << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << llendl; desired_size = MAX_IMAGE_DATA_SIZE; + desired_discard = 0; } else if (desired_discard == 0) { diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 9573b884eb..98731f90f4 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -412,7 +412,7 @@ void LLGLTexMemBar::draw() F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ; F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ; S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); - S32 h_offset = (S32)((texture_bar_height + 2.5f) * mTextureView->mNumTextureBars + 2.5f); + S32 v_offset = (S32)((texture_bar_height + 2.5f) * mTextureView->mNumTextureBars + 2.5f); //---------------------------------------------------------------------------- LLGLSUIDefault gls_ui; LLColor4 text_color(1.f, 1.f, 1.f, 0.75f); @@ -428,14 +428,14 @@ void LLGLTexMemBar::draw() cache_usage, cache_max_usage); //, cache_entries, cache_max_entries - LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, h_offset + line_height*3, + LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3, text_color, LLFontGL::LEFT, LLFontGL::TOP); //---------------------------------------------------------------------------- #if 0 S32 bar_left = 400; S32 bar_width = 200; - S32 top = line_height*3 - 2 + h_offset; + S32 top = line_height*3 - 2 + v_offset; S32 bottom = top - 6; S32 left = bar_left; S32 right = left + bar_width; @@ -494,18 +494,18 @@ void LLGLTexMemBar::draw() #endif //---------------------------------------------------------------------------- - text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d RAW:%d HTP:%d CRE:%d", + text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d RAW:%d HTP:%d DEC:%d CRE:%d", gTextureList.getNumImages(), LLAppViewer::getTextureFetch()->getNumRequests(), LLAppViewer::getTextureFetch()->getNumDeletes(), LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount, LLAppViewer::getTextureCache()->getNumReads(), LLAppViewer::getTextureCache()->getNumWrites(), LLLFSThread::sLocal->getPending(), - LLAppViewer::getImageDecodeThread()->getPending(), LLImageRaw::sRawImageCount, LLAppViewer::getTextureFetch()->getNumHTTPRequests(), + LLAppViewer::getImageDecodeThread()->getPending(), gTextureList.mCreateTextureList.size()); - LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, h_offset + line_height*2, + LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*2, text_color, LLFontGL::LEFT, LLFontGL::TOP); @@ -515,40 +515,40 @@ void LLGLTexMemBar::draw() color = bandwidth > max_bandwidth ? LLColor4::red : bandwidth > max_bandwidth*.75f ? LLColor4::yellow : text_color; color[VALPHA] = text_color[VALPHA]; text = llformat("BW:%.0f/%.0f",bandwidth, max_bandwidth); - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*2, + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, v_offset + line_height*2, color, LLFontGL::LEFT, LLFontGL::TOP); S32 dx1 = 0; if (LLAppViewer::getTextureFetch()->mDebugPause) { - LLFontGL::getFontMonospace()->renderUTF8(std::string("!"), 0, title_x1, h_offset + line_height, + LLFontGL::getFontMonospace()->renderUTF8(std::string("!"), 0, title_x1, v_offset + line_height, text_color, LLFontGL::LEFT, LLFontGL::TOP); dx1 += 8; } if (mTextureView->mFreezeView) { - LLFontGL::getFontMonospace()->renderUTF8(std::string("*"), 0, title_x1, h_offset + line_height, + LLFontGL::getFontMonospace()->renderUTF8(std::string("*"), 0, title_x1, v_offset + line_height, text_color, LLFontGL::LEFT, LLFontGL::TOP); dx1 += 8; } if (mTextureView->mOrderFetch) { - LLFontGL::getFontMonospace()->renderUTF8(title_string1b, 0, title_x1+dx1, h_offset + line_height, + LLFontGL::getFontMonospace()->renderUTF8(title_string1b, 0, title_x1+dx1, v_offset + line_height, text_color, LLFontGL::LEFT, LLFontGL::TOP); } else { - LLFontGL::getFontMonospace()->renderUTF8(title_string1a, 0, title_x1+dx1, h_offset + line_height, + LLFontGL::getFontMonospace()->renderUTF8(title_string1a, 0, title_x1+dx1, v_offset + line_height, text_color, LLFontGL::LEFT, LLFontGL::TOP); } - LLFontGL::getFontMonospace()->renderUTF8(title_string2, 0, title_x2, h_offset + line_height, + LLFontGL::getFontMonospace()->renderUTF8(title_string2, 0, title_x2, v_offset + line_height, text_color, LLFontGL::LEFT, LLFontGL::TOP); - LLFontGL::getFontMonospace()->renderUTF8(title_string3, 0, title_x3, h_offset + line_height, + LLFontGL::getFontMonospace()->renderUTF8(title_string3, 0, title_x3, v_offset + line_height, text_color, LLFontGL::LEFT, LLFontGL::TOP); - LLFontGL::getFontMonospace()->renderUTF8(title_string4, 0, title_x4, h_offset + line_height, + LLFontGL::getFontMonospace()->renderUTF8(title_string4, 0, title_x4, v_offset + line_height, text_color, LLFontGL::LEFT, LLFontGL::TOP); } diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 2a56b2cd3a..96d1624cd4 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -245,7 +245,7 @@ void LLToast::setVisible(BOOL show) if(show) { setBackgroundOpaque(TRUE); - if(!mTimer.getStarted()) + if(!mTimer.getStarted() && mCanFade) { mTimer.start(); } @@ -266,8 +266,6 @@ void LLToast::onMouseEnter(S32 x, S32 y, MASK mask) { mOnToastHoverSignal(this, MOUSE_ENTER); - setBackgroundOpaque(TRUE); - //toasts fading is management by Screen Channel sendChildToFront(mHideBtn); diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index c48301fa1e..c3ccb9380b 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -279,7 +279,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal mLineEditor->reshape(leditor_rect.getWidth(), leditor_rect.getHeight()); mLineEditor->setRect(leditor_rect); mLineEditor->setText(edit_text_contents); - mLineEditor->setMaxTextLength(STD_STRING_STR_LEN); + mLineEditor->setMaxTextLength(STD_STRING_STR_LEN - 1); // make sure all edit keys get handled properly (DEV-22396) mLineEditor->setHandleEditKeysDirectly(TRUE); @@ -385,6 +385,12 @@ BOOL LLToastAlertPanel::handleKeyHere(KEY key, MASK mask ) { if( KEY_RETURN == key && mask == MASK_NONE ) { + LLButton* defaultBtn = getDefaultButton(); + if(defaultBtn && defaultBtn->getVisible() && defaultBtn->getEnabled()) + { + // If we have a default button, click it when return is pressed + defaultBtn->onCommit(); + } return TRUE; } else if (KEY_RIGHT == key) diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h index 875ab82c54..43e105a4f1 100644 --- a/indra/newview/lltoastalertpanel.h +++ b/indra/newview/lltoastalertpanel.h @@ -37,6 +37,7 @@ #include "llfloater.h" #include "llui.h" #include "llnotificationptr.h" +#include "llerror.h" class LLButton; class LLCheckBoxCtrl; @@ -53,6 +54,7 @@ class LLLineEditor; class LLToastAlertPanel : public LLToastPanel { + LOG_CLASS(LLToastAlertPanel); public: typedef bool (*display_callback_t)(S32 modal); diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index b7add03e0e..d62017cc2f 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -35,13 +35,14 @@ #include "llnotifications.h" #include "llinstantmessage.h" +#include "llviewerchat.h" const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 6; //-------------------------------------------------------------------------- LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notification), - mAvatar(NULL), mUserName(NULL), - mTime(NULL), mMessage(NULL) + mAvatar(NULL), mUserName(NULL), + mTime(NULL), mMessage(NULL) { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_instant_message.xml"); @@ -52,8 +53,11 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif mMessage = getChild<LLTextBox>("message"); LLStyle::Params style_params; - style_params.font.name(LLFontGL::nameFromFont(style_params.font)); - style_params.font.size(LLFontGL::sizeFromFont(style_params.font)); + LLFontGL* fontp = LLViewerChat::getChatFont(); + std::string font_name = LLFontGL::nameFromFont(fontp); + std::string font_size = LLFontGL::sizeFromFont(fontp); + style_params.font.name(font_name); + style_params.font.size(font_size); style_params.font.style = "UNDERLINE"; //Handle IRC styled /me messages. @@ -63,13 +67,16 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif mMessage->clear(); style_params.font.style ="ITALIC"; - mMessage->appendText(p.from + " ", FALSE, style_params); + mMessage->appendText(p.from, FALSE, style_params); style_params.font.style = "ITALIC"; mMessage->appendText(p.message.substr(3), FALSE, style_params); } else + { mMessage->setValue(p.message); + } + mUserName->setValue(p.from); mTime->setValue(p.time); mSessionID = p.session_id; diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 74fbce890d..5f66e6b409 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -101,16 +101,13 @@ BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktyp BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) { //left mouse down always picks transparent - gViewerWindow->pickAsync(x, y, mask, leftMouseCallback, TRUE); + mPick = gViewerWindow->pickImmediate(x, y, TRUE); + mPick.mKeyMask = mask; mGrabMouseButtonDown = TRUE; - return TRUE; -} + + pickLeftMouseDownCallback(); -// static -void LLToolPie::leftMouseCallback(const LLPickInfo& pick_info) -{ - LLToolPie::getInstance()->mPick = pick_info; - LLToolPie::getInstance()->pickLeftMouseDownCallback(); + return TRUE; } // Spawn context menus on right mouse down so you can drag over and select @@ -118,8 +115,13 @@ void LLToolPie::leftMouseCallback(const LLPickInfo& pick_info) BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask) { // don't pick transparent so users can't "pay" transparent objects - gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE); + mPick = gViewerWindow->pickImmediate(x, y, FALSE); + mPick.mKeyMask = mask; + // claim not handled so UI focus stays same + + pickRightMouseDownCallback(); + return FALSE; } @@ -134,13 +136,6 @@ BOOL LLToolPie::handleScrollWheel(S32 x, S32 y, S32 clicks) return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks); } -// static -void LLToolPie::rightMouseCallback(const LLPickInfo& pick_info) -{ - LLToolPie::getInstance()->mPick = pick_info; - LLToolPie::getInstance()->pickRightMouseDownCallback(); -} - // True if you selected an object. BOOL LLToolPie::pickLeftMouseDownCallback() { @@ -731,14 +726,13 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask) // *HACK: We may select this object, so pretend it was clicked mPick = mHoverPick; LLInspector::Params p; + p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>()); p.message(avatar_name); p.image(LLUI::getUIImage("Info")); p.click_callback(boost::bind(showAvatarInspector, hover_object->getID())); p.visible_time_near(6.f); p.visible_time_far(3.f); p.wrap(false); - - p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>()); LLToolTipMgr::instance().show(p); } @@ -822,6 +816,7 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask) // We may select this object, so pretend it was clicked mPick = mHoverPick; LLInspector::Params p; + p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>()); p.message(tooltip_msg); p.image(LLUI::getUIImage("Info_Off")); p.click_callback(boost::bind(showObjectInspector, hover_object->getID(), mHoverPick.mObjectFace)); @@ -833,8 +828,6 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask) p.visible_time_near(6.f); p.visible_time_far(3.f); p.wrap(false); - - p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>()); LLToolTipMgr::instance().show(p); } diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index 3660c68552..5f0e28fa95 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -71,9 +71,6 @@ public: LLObjectSelection* getLeftClickSelection() { return (LLObjectSelection*)mLeftClickSelection; } void resetSelection(); - static void leftMouseCallback(const LLPickInfo& pick_info); - static void rightMouseCallback(const LLPickInfo& pick_info); - static void selectionPropertiesReceived(); static void showAvatarInspector(const LLUUID& avatar_id); diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp index 7befb87248..347399f239 100644 --- a/indra/newview/lltransientfloatermgr.cpp +++ b/indra/newview/lltransientfloatermgr.cpp @@ -37,6 +37,7 @@ #include "llrootview.h" #include "llviewerwindow.h" #include "lldockablefloater.h" +#include "llmenugl.h" LLTransientFloaterMgr::LLTransientFloaterMgr() @@ -87,6 +88,13 @@ void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y, for (controls_set_t::iterator it = mControlsSet.begin(); it != mControlsSet.end(); it++) { + // don't hide transient floater if any context menu opened + if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL) + { + hide = false; + break; + } + LLView* control_view = *it; if (!control_view->getVisible()) { diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index e7f904023a..38103f9e41 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -211,19 +211,31 @@ void audio_update_wind(bool force_update) // if (force_update || (last_camera_water_height * camera_water_height) < 0.f) { + static LLUICachedControl<F32> rolloff("AudioLevelRolloff", 1.0f); if (camera_water_height < 0.f) { - gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff") * LL_ROLLOFF_MULTIPLIER_UNDER_WATER); + gAudiop->setRolloffFactor(rolloff * LL_ROLLOFF_MULTIPLIER_UNDER_WATER); } else { - gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff")); + gAudiop->setRolloffFactor(rolloff); } } - // this line rotates the wind vector to be listener (agent) relative - // Only use the agent's motion to compute wind noise, otherwise the world - // feels desolate on login when you are standing still. - gRelativeWindVec = gAgent.getFrameAgent().rotateToLocal( -gAgent.getVelocity() ); + + // Scale down the contribution of weather-simulation wind to the + // ambient wind noise. Wind velocity averages 3.5 m/s, with gusts to 7 m/s + // whereas steady-state avatar walk velocity is only 3.2 m/s. + // Without this the world feels desolate on first login when you are + // standing still. + static LLUICachedControl<F32> wind_level("AudioLevelWind", 0.5f); + LLVector3 scaled_wind_vec = gWindVec * wind_level; + + // Mix in the avatar's motion, subtract because when you walk north, + // the apparent wind moves south. + LLVector3 final_wind_vec = scaled_wind_vec - gAgent.getVelocity(); + + // rotate the wind vector to be listener (agent) relative + gRelativeWindVec = gAgent.getFrameAgent().rotateToLocal( final_wind_vec ); // don't use the setter setMaxWindGain() because we don't // want to screw up the fade-in on startup by setting actual source gain diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 68a5147bc7..3dac0ee452 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -713,7 +713,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first. F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time - max_image_decode_time = llclamp(max_image_decode_time, 0.001f, 0.005f ); // min 1ms/frame, max 5ms/frame) + max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame) gTextureList.updateImages(max_image_decode_time); //remove dead textures from GL diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 35c9a1d367..23bdbc7381 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -53,7 +53,6 @@ #include "llfloaterbuyland.h" #include "llfloaterbulkpermission.h" #include "llfloaterbump.h" -#include "llfloatercall.h" #include "llfloatercamera.h" #include "llfloaterchat.h" #include "llfloaterchatterbox.h" @@ -94,6 +93,7 @@ #include "llfloaterregioninfo.h" #include "llfloaterreporter.h" #include "llfloaterscriptdebug.h" +#include "llfloaterscriptlimits.h" #include "llfloatersellland.h" #include "llfloatersettingsdebug.h" #include "llfloatersnapshot.h" @@ -110,6 +110,7 @@ #include "llfloaterwater.h" #include "llfloaterwhitelistentry.h" #include "llfloaterwindlight.h" +#include "llfloaterwindowsize.h" #include "llfloaterworldmap.h" #include "llimfloatercontainer.h" #include "llinspectavatar.h" @@ -241,6 +242,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("script_debug", "floater_script_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebug>); LLFloaterReg::add("script_debug_output", "floater_script_debug_panel.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebugOutput>); LLFloaterReg::add("script_floater", "floater_script.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLScriptFloater>); + LLFloaterReg::add("script_limits", "floater_script_limits.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptLimits>); LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater); LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>); LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>); @@ -258,6 +260,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("voice_controls", "floater_voice_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLCallFloater>); LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWhiteListEntry>); + LLFloaterWindowSizeUtil::registerFloater(); LLFloaterReg::add("world_map", "floater_world_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWorldMap>); // *NOTE: Please keep these alphabetized for easier merges diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index df62c9628d..bf96472e7e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -166,11 +166,18 @@ public: // 2xx status codes indicate success. // Most 4xx status codes are successful enough for our purposes. // 499 is the error code for host not found, timeout, etc. + // 500 means "Internal Server error" but we decided it's okay to + // accept this and go past it in the MIME type probe + // 302 means the resource can be found temporarily in a different place - added this for join.secondlife.com + // 499 is a code specifc to join.secondlife.com (????) apparently safe to ignore if( ((status >= 200) && (status < 300)) || - ((status >= 400) && (status < 499)) ) + ((status >= 400) && (status < 499)) || + (status == 500) || + (status == 302) || + (status == 499) + ) { // The probe was successful. - if(mime_type.empty()) { // Some sites don't return any content-type header at all. diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 28fb379960..63f461b4c4 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -187,6 +187,7 @@ public: std::string getMediaURL() const { return mMediaURL; } std::string getCurrentMediaURL(); std::string getHomeURL() { return mHomeURL; } + std::string getMediaEntryURL() { return mMediaEntryURL; } void setHomeURL(const std::string& home_url) { mHomeURL = home_url; }; void clearCache(); std::string getMimeType() { return mMimeType; } diff --git a/indra/newview/llviewermedia_streamingaudio.cpp b/indra/newview/llviewermedia_streamingaudio.cpp index 90cfb85821..67b051e536 100644 --- a/indra/newview/llviewermedia_streamingaudio.cpp +++ b/indra/newview/llviewermedia_streamingaudio.cpp @@ -1,7 +1,7 @@ /** * @file llviewermedia_streamingaudio.h * @author Tofu Linden, Sam Kolb - * @brief LLStreamingAudio_MediaPlugins implementation - an implementation of the streaming audio interface which is implemented as a client of the media plugins API. + * @brief LLStreamingAudio_MediaPlugins implementation - an implementation of the streaming audio interface which is implemented as a client of the media plugin API. * * $LicenseInfo:firstyear=2009&license=viewergpl$ * @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "linden_common.h" #include "llpluginclassmedia.h" +#include "llpluginclassmediaowner.h" #include "llviewermedia.h" #include "llviewermedia_streamingaudio.h" @@ -61,18 +62,18 @@ void LLStreamingAudio_MediaPlugins::start(const std::string& url) if (!mMediaPlugin) // lazy-init the underlying media plugin { mMediaPlugin = initializeMedia("audio/mpeg"); // assumes that whatever media implementation supports mp3 also supports vorbis. - llinfos << "mMediaPlugin is now " << mMediaPlugin << llendl; + llinfos << "streaming audio mMediaPlugin is now " << mMediaPlugin << llendl; } if(!mMediaPlugin) return; - + if (!url.empty()) { llinfos << "Starting internet stream: " << url << llendl; mURL = url; mMediaPlugin->loadURI ( url ); mMediaPlugin->start(); - llinfos << "Playing....." << llendl; + llinfos << "Playing stream..." << llendl; } else { llinfos << "setting stream to NULL"<< llendl; mURL.clear(); @@ -82,6 +83,7 @@ void LLStreamingAudio_MediaPlugins::start(const std::string& url) void LLStreamingAudio_MediaPlugins::stop() { + llinfos << "Stopping internet stream." << llendl; if(mMediaPlugin) { mMediaPlugin->stop(); @@ -97,10 +99,12 @@ void LLStreamingAudio_MediaPlugins::pause(int pause) if(pause) { + llinfos << "Pausing internet stream." << llendl; mMediaPlugin->pause(); } else { + llinfos << "Unpausing internet stream." << llendl; mMediaPlugin->start(); } } @@ -114,20 +118,21 @@ void LLStreamingAudio_MediaPlugins::update() int LLStreamingAudio_MediaPlugins::isPlaying() { if (!mMediaPlugin) - return 0; + return 0; // stopped - // *TODO: can probably do better than this - if (mMediaPlugin->isPluginRunning()) - { - return 1; // Active and playing - } + LLPluginClassMediaOwner::EMediaStatus status = + mMediaPlugin->getStatus(); - if (mMediaPlugin->isPluginExited()) + switch (status) { + case LLPluginClassMediaOwner::MEDIA_LOADING: // but not MEDIA_LOADED + case LLPluginClassMediaOwner::MEDIA_PLAYING: + return 1; // Active and playing + case LLPluginClassMediaOwner::MEDIA_PAUSED: + return 2; // paused + default: return 0; // stopped } - - return 2; // paused } void LLStreamingAudio_MediaPlugins::setGain(F32 vol) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 23bcca9603..5445a79137 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -70,6 +70,7 @@ #include "lltooltip.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" +#include "llimview.h" #include "llinventorybridge.h" #include "llpanellogin.h" #include "llpanelblockedlist.h" @@ -2465,7 +2466,7 @@ class LLViewJoystickFlycam : public view_listener_t class LLViewCheckJoystickFlycam : public view_listener_t { bool handleEvent(const LLSD& userdata) - { + { bool new_value = LLViewerJoystick::getInstance()->getOverrideCamera(); return new_value; } @@ -3703,6 +3704,7 @@ void reset_view_final( BOOL proceed ) } gAgent.resetView(TRUE, TRUE); + gAgent.setLookAt(LOOKAT_TARGET_CLEAR); } class LLViewLookAtLastChatter : public view_listener_t @@ -6479,21 +6481,27 @@ void menu_toggle_attached_particles(void* user_data) LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); } -class LLAdvancedHandleAttchedLightParticles: public view_listener_t +class LLAdvancedHandleAttachedLightParticles: public view_listener_t { bool handleEvent(const LLSD& userdata) { std::string control_name = userdata.asString(); + + // toggle the control + gSavedSettings.setBOOL(control_name, + !gSavedSettings.getBOOL(control_name)); + + // update internal flags if (control_name == "RenderAttachedLights") -{ + { menu_toggle_attached_lights(NULL); -} + } else if (control_name == "RenderAttachedParticles") -{ + { menu_toggle_attached_particles(NULL); -} + } return true; -} + } }; class LLSomethingSelected : public view_listener_t @@ -7423,12 +7431,17 @@ class LLEditTakeOff : public view_listener_t { std::string clothing = userdata.asString(); if (clothing == "all") - LLAgentWearables::userRemoveAllClothes(); + LLWearableBridge::removeAllClothesFromAvatar(); else { EWearableType type = LLWearableDictionary::typeNameToType(clothing); if (type >= WT_SHAPE && type < WT_COUNT) - LLAgentWearables::userRemoveWearable(type); + { + // MULTI-WEARABLES + LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>(gAgentWearables.getWearableInventoryItem(type,0)); + LLWearableBridge::removeItemFromAvatar(item); + } + } return true; } @@ -7758,7 +7771,7 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedVectorizePerfTest(), "Advanced.VectorizePerfTest"); view_listener_t::addMenu(new LLAdvancedToggleFrameTest(), "Advanced.ToggleFrameTest"); view_listener_t::addMenu(new LLAdvancedCheckFrameTest(), "Advanced.CheckFrameTest"); - view_listener_t::addMenu(new LLAdvancedHandleAttchedLightParticles(), "Advanced.HandleAttchedLightParticles"); + view_listener_t::addMenu(new LLAdvancedHandleAttachedLightParticles(), "Advanced.HandleAttachedLightParticles"); #ifdef TOGGLE_HACKED_GODLIKE_VIEWER diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 6a31bbfa1e..6f9e551649 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -33,7 +33,9 @@ #include "llviewerprecompiledheaders.h" #include "llviewermessage.h" +#include "llanimationstates.h" #include "llaudioengine.h" +#include "llavataractions.h" #include "lscript_byteformat.h" #include "lleconomy.h" #include "llfloaterreg.h" @@ -192,19 +194,25 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) msg->sendReliable(LLHost(payload["sender"].asString())); break; } - case 1: - { - // decline - // We no longer notify other viewers, but we DO still send - // the rejection to the simulator to delete the pending userop. - msg->newMessageFast(_PREHASH_DeclineFriendship); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_TransactionBlock); - msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); - msg->sendReliable(LLHost(payload["sender"].asString())); - break; + case 1: // Decline + case 2: // Send IM - decline and start IM session + { + // decline + // We no longer notify other viewers, but we DO still send + // the rejection to the simulator to delete the pending userop. + msg->newMessageFast(_PREHASH_DeclineFriendship); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_TransactionBlock); + msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); + msg->sendReliable(LLHost(payload["sender"].asString())); + + // start IM session + if(2 == option) + { + LLAvatarActions::startIM(payload["from_id"].asUUID()); + } } default: // close button probably, possibly timed out @@ -906,6 +914,18 @@ void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& f LLFloaterReg::showInstance("preview_texture", LLSD(item_id), take_focus); break; } + case LLAssetType::AT_ANIMATION: + LLFloaterReg::showInstance("preview_anim", LLSD(item_id), take_focus); + break; + case LLAssetType::AT_GESTURE: + LLFloaterReg::showInstance("preview_gesture", LLSD(item_id), take_focus); + break; + case LLAssetType::AT_SCRIPT: + LLFloaterReg::showInstance("preview_script", LLSD(item_id), take_focus); + break; + case LLAssetType::AT_SOUND: + LLFloaterReg::showInstance("preview_sound", LLSD(item_id), take_focus); + break; default: break; } @@ -1146,9 +1166,9 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& default: LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL; break; - } // end switch (mIM) - - // Show falls through to accept. + } + break; + // end switch (mIM) case IOR_ACCEPT: msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1)); @@ -1837,7 +1857,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // This is a block, modeless dialog. //*TODO: Translate args["MESSAGE"] = message; - LLNotificationsUtil::add("SystemMessage", args); + LLNotificationsUtil::add("SystemMessageTip", args); } break; case IM_GROUP_NOTICE: @@ -2514,14 +2534,9 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) std::string prefix = mesg.substr(0, 4); if (prefix == "/me " || prefix == "/me'") { -// chat.mText = from_name; -// chat.mText += mesg.substr(3); ircstyle = TRUE; } -// else -// { - chat.mText = mesg; -// } + chat.mText = mesg; // Look for the start of typing so we can put "..." in the bubbles. if (CHAT_TYPE_START == chat.mChatType) @@ -3934,6 +3949,17 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data) avatarp->mSignaledAnimations[animation_id] = anim_sequence_id; + // *HACK: Disabling flying mode if it has been enabled shortly before the agent + // stand up animation is signaled. In this case we don't get a signal to start + // flying animation from server, the AGENT_CONTROL_FLY flag remains set but the + // avatar does not play flying animation, so we switch flying mode off. + // See LLAgent::setFlying(). This may cause "Stop Flying" button to blink. + // See EXT-2781. + if (animation_id == ANIM_AGENT_STANDUP && gAgent.getFlying()) + { + gAgent.setFlying(FALSE); + } + if (i < num_source_blocks) { mesgsys->getUUIDFast(_PREHASH_AnimationSourceList, _PREHASH_ObjectID, object_id, i); diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 90a7ee98b9..86f0f4e04e 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -182,7 +182,7 @@ void LLViewerParcelMedia::play(LLParcel* parcel) if (!parcel) return; - if (!gSavedSettings.getBOOL("AudioSteamingMedia") || !gSavedSettings.getBOOL("AudioStreamingVideo")) + if (!gSavedSettings.getBOOL("AudioStreamingMedia") || !gSavedSettings.getBOOL("AudioStreamingVideo")) return; std::string media_url = parcel->getMediaURL(); @@ -594,8 +594,8 @@ bool callback_play_media(const LLSD& notification, const LLSD& response, LLParce if (option == 0) { gSavedSettings.setBOOL("AudioStreamingVideo", TRUE); - if(!gSavedSettings.getBOOL("AudioSteamingMedia")) - gSavedSettings.setBOOL("AudioSteamingMedia", TRUE); + if(!gSavedSettings.getBOOL("AudioStreamingMedia")) + gSavedSettings.setBOOL("AudioStreamingMedia", TRUE); LLViewerParcelMedia::play(parcel); } else diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index be68a2ef42..87a9eae028 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1754,7 +1754,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use void optionally_start_music(const std::string& music_url) { - if (gSavedSettings.getBOOL("AudioStreamingMusic") && gSavedSettings.getBOOL("AudioSteamingMedia")) + if (gSavedSettings.getBOOL("AudioStreamingMusic") && gSavedSettings.getBOOL("AudioStreamingMedia")) { // Make the user click the start button on the overlay bar. JC // llinfos << "Starting parcel music " << music_url << llendl; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index d1c9840a97..77d2d493bd 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1421,6 +1421,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url) setCapability("Seed", url); LLSD capabilityNames = LLSD::emptyArray(); + + capabilityNames.append("AttachmentResources"); capabilityNames.append("ChatSessionRequest"); capabilityNames.append("CopyInventoryFromNotecard"); capabilityNames.append("DispatchRegionInfo"); @@ -1434,6 +1436,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("GetTexture"); capabilityNames.append("GroupProposalBallot"); capabilityNames.append("HomeLocation"); + capabilityNames.append("LandResources"); capabilityNames.append("MapLayer"); capabilityNames.append("MapLayerGod"); capabilityNames.append("NewFileAgentInventory"); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index a1a3bc6d6a..8059f866ba 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -656,9 +656,9 @@ void update_statistics(U32 frame_count) gObjectBits = 0; // gDecodedBits = 0; - // Only update texture stats ones per second so that they are less noisy + // Only update texture stats periodically so that they are less noisy { - static const F32 texture_stats_freq = 1.f; + static const F32 texture_stats_freq = 10.f; static LLFrameTimer texture_stats_timer; if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq) { diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index b45148a186..f825eaa8ab 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -495,6 +495,8 @@ void LLViewerTexture::init(bool firstinit) mNeedsResetMaxVirtualSize = FALSE ; mAdditionalDecodePriority = 0.f ; mParcelMedia = NULL ; + mNumFaces = 0 ; + mFaceList.clear() ; } //virtual @@ -627,13 +629,55 @@ void LLViewerTexture::setKnownDrawSize(S32 width, S32 height) //virtual void LLViewerTexture::addFace(LLFace* facep) { - mFaceList.push_back(facep) ; + if(mNumFaces >= mFaceList.size()) + { + mFaceList.resize(2 * mNumFaces + 1) ; + } + mFaceList[mNumFaces] = facep ; + facep->setIndexInTex(mNumFaces) ; + mNumFaces++ ; + mLastFaceListUpdateTimer.reset() ; } //virtual void LLViewerTexture::removeFace(LLFace* facep) { - mFaceList.remove(facep) ; + if(mNumFaces > 1) + { + S32 index = facep->getIndexInTex() ; + mFaceList[index] = mFaceList[--mNumFaces] ; + mFaceList[index]->setIndexInTex(index) ; + } + else + { + mFaceList.clear() ; + mNumFaces = 0 ; + } + mLastFaceListUpdateTimer.reset() ; +} + +S32 LLViewerTexture::getNumFaces() const +{ + return mNumFaces ; +} + +void LLViewerTexture::reorganizeFaceList() +{ + static const F32 MAX_WAIT_TIME = 20.f; // seconds + static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ; + + if(mNumFaces + MAX_EXTRA_BUFFER_SIZE > mFaceList.size()) + { + return ; + } + + if(mLastFaceListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME) + { + return ; + } + + mLastFaceListUpdateTimer.reset() ; + mFaceList.erase(mFaceList.begin() + mNumFaces, mFaceList.end()); } //virtual @@ -1497,7 +1541,8 @@ F32 LLViewerFetchedTexture::calcDecodePriority() { priority += 10000000.f; } - else if(mAdditionalDecodePriority > 0.0f) + + if(mAdditionalDecodePriority > 0.0f) { // 1-9 S32 additional_priority = (S32)(1.0f + mAdditionalDecodePriority*8.0f + .5f); // round @@ -1530,23 +1575,28 @@ void LLViewerFetchedTexture::updateVirtualSize() { addTextureStats(0.f, FALSE) ;//reset } - if(mFaceList.size() > 0) + + for(U32 i = 0 ; i < mNumFaces ; i++) { - for(std::list<LLFace*>::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + LLFace* facep = mFaceList[i] ; + if(facep->getDrawable()->isRecentlyVisible()) { - LLFace* facep = *iter ; - if(facep->getDrawable()->isRecentlyVisible()) - { - addTextureStats(facep->getVirtualSize()) ; - setAdditionalDecodePriority(facep->getImportanceToCamera()) ; - } - } + addTextureStats(facep->getVirtualSize()) ; + setAdditionalDecodePriority(facep->getImportanceToCamera()) ; + } } mNeedsResetMaxVirtualSize = TRUE ; + reorganizeFaceList() ; } bool LLViewerFetchedTexture::updateFetch() { + static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); + if(textures_decode_disabled) + { + return false ; + } + mFetchState = 0; mFetchPriority = 0; mFetchDeltaTime = 999999.f; @@ -1627,9 +1677,9 @@ bool LLViewerFetchedTexture::updateFetch() mComponents = mRawImage->getComponents(); mGLTexturep->setComponents(mComponents) ; - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + for(U32 i = 0 ; i < mNumFaces ; i++) { - (*iter)->dirtyTexture() ; + mFaceList[i]->dirtyTexture() ; } } mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; @@ -2361,16 +2411,13 @@ void LLViewerFetchedTexture::resetFaceAtlas() //invalidate all atlas slots for this image. void LLViewerFetchedTexture::invalidateAtlas(BOOL rebuild_geom) { - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + for(U32 i = 0 ; i < mNumFaces ; i++) { - if(*iter) + LLFace* facep = mFaceList[i] ; + facep->removeAtlas() ; + if(rebuild_geom && facep->getDrawable() && facep->getDrawable()->getSpatialGroup()) { - LLFace* facep = (LLFace*)*iter ; - facep->removeAtlas() ; - if(rebuild_geom && facep->getDrawable() && facep->getDrawable()->getSpatialGroup()) - { - facep->getDrawable()->getSpatialGroup()->setState(LLSpatialGroup::GEOM_DIRTY); - } + facep->getDrawable()->getSpatialGroup()->setState(LLSpatialGroup::GEOM_DIRTY); } } } @@ -2381,7 +2428,7 @@ BOOL LLViewerFetchedTexture::insertToAtlas() { return FALSE ; } - if(mFaceList.size() < 1) + if(getNumFaces() < 1) { return FALSE ; } @@ -2405,12 +2452,10 @@ BOOL LLViewerFetchedTexture::insertToAtlas() //if the atlas slot pointers for some faces are null, process them later. ll_face_list_t waiting_list ; - - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + for(U32 i = 0 ; i < mNumFaces ; i++) { - if(*iter) { - facep = (LLFace*)*iter ; + facep = mFaceList[i] ; //face can not use atlas. if(!facep->canUseAtlas()) @@ -2722,7 +2767,7 @@ void LLViewerMediaTexture::updateClass() #if 0 //force to play media. - gSavedSettings.setBOOL("AudioSteamingMedia", true) ; + gSavedSettings.setBOOL("AudioStreamingMedia", true) ; gSavedSettings.setBOOL("AudioStreamingVideo", true) ; #endif @@ -2868,9 +2913,10 @@ BOOL LLViewerMediaTexture::findFaces() if(tex) //this media is a parcel media for tex. { const ll_face_list_t* face_list = tex->getFaceList() ; - for(ll_face_list_t::const_iterator iter = face_list->begin(); iter != face_list->end(); ++iter) + U32 end = tex->getNumFaces() ; + for(U32 i = 0 ; i < end ; i++) { - mMediaFaceList.push_back(*iter) ; + mMediaFaceList.push_back((*face_list)[i]) ; } } @@ -2949,7 +2995,7 @@ void LLViewerMediaTexture::removeMediaFromFace(LLFace* facep) switchTexture(facep) ; mIsPlaying = TRUE ; //set the flag back. - if(mFaceList.empty()) //no face referencing to this media + if(getNumFaces() < 1) //no face referencing to this media { stopPlaying() ; } @@ -3005,17 +3051,17 @@ void LLViewerMediaTexture::removeFace(LLFace* facep) // //we have some trouble here: the texture of the face is changed. //we need to find the former texture, and remove it from the list to avoid memory leaking. - if(mFaceList.empty()) + if(!mNumFaces) { mTextureList.clear() ; return ; } - S32 end = mFaceList.size() ; + S32 end = getNumFaces() ; std::vector<const LLTextureEntry*> te_list(end) ; S32 i = 0 ; - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + for(U32 j = 0 ; j < mNumFaces ; j++) { - te_list[i++] = (*iter)->getTextureEntry() ;//all textures are in use. + te_list[i++] = mFaceList[j]->getTextureEntry() ;//all textures are in use. } for(std::list< LLPointer<LLViewerTexture> >::iterator iter = mTextureList.begin(); iter != mTextureList.end(); ++iter) @@ -3133,16 +3179,9 @@ void LLViewerMediaTexture::setPlaying(BOOL playing) } else //stop playing this media { - if(mFaceList.empty()) + for(U32 i = mNumFaces ; i ; i--) { - return ; - } - - ll_face_list_t::iterator cur ; - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter!= mFaceList.end(); ) - { - cur = iter++ ; - switchTexture(*cur) ; //cur could be removed in this function. + switchTexture(mFaceList[i - 1]) ; //current face could be removed in this function. } } return ; @@ -3164,17 +3203,14 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() if(mIsPlaying) //media is playing { - if(mFaceList.size() > 0) - { - for(std::list<LLFace*>::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + for(U32 i = 0 ; i < mNumFaces ; i++) + { + LLFace* facep = mFaceList[i] ; + if(facep->getDrawable()->isRecentlyVisible()) { - LLFace* facep = *iter ; - if(facep->getDrawable()->isRecentlyVisible()) - { - addTextureStats(facep->getVirtualSize()) ; - } - } - } + addTextureStats(facep->getVirtualSize()) ; + } + } } else //media is not in playing { @@ -3194,6 +3230,7 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() } mNeedsResetMaxVirtualSize = TRUE ; + reorganizeFaceList() ; return mMaxVirtualSize ; } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index d6fbd5d570..6aaaa4021b 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -134,7 +134,7 @@ public: static S32 getIndexFromCategory(S32 category) ; static S32 getCategoryFromIndex(S32 index) ; - typedef std::list<LLFace*> ll_face_list_t ; + typedef std::vector<LLFace*> ll_face_list_t ; protected: virtual ~LLViewerTexture(); @@ -175,7 +175,8 @@ public: virtual void addFace(LLFace* facep) ; virtual void removeFace(LLFace* facep) ; - const ll_face_list_t* getFaceList() const {return &mFaceList ;} + S32 getNumFaces() const; + const ll_face_list_t* getFaceList() const {return &mFaceList;} void generateGLTexture() ; void destroyGLTexture() ; @@ -239,13 +240,14 @@ public: /*virtual*/ void updateBindStatsForTester() ; protected: void cleanup() ; - void init(bool firstinit) ; + void init(bool firstinit) ; + void reorganizeFaceList() ; private: //note: do not make this function public. /*virtual*/ LLImageGL* getGLTexture() const ; virtual void switchToCachedImage(); - + protected: LLUUID mID; S32 mBoostLevel; // enum describing priority level @@ -257,14 +259,16 @@ protected: mutable S8 mNeedsGLTexture; mutable BOOL mNeedsResetMaxVirtualSize ; mutable F32 mAdditionalDecodePriority; // priority add to mDecodePriority. - LLFrameTimer mLastReferencedTimer; - - ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture + LLFrameTimer mLastReferencedTimer; //GL texture LLPointer<LLImageGL> mGLTexturep ; S8 mDontDiscard; // Keep full res version of this image (for UI, etc) + ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture + U32 mNumFaces ; + LLFrameTimer mLastFaceListUpdateTimer ; + //do not use LLPointer here. LLViewerMediaTexture* mParcelMedia ; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 71fe8dd773..21bf567b0c 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -185,7 +185,6 @@ #include "llworldmapview.h" #include "pipeline.h" #include "llappviewer.h" -#include "llurlsimstring.h" #include "llviewerdisplay.h" #include "llspatialpartition.h" #include "llviewerjoystick.h" diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 69d2458217..18cdd23ed9 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -33,7 +33,6 @@ #include "llviewerprecompiledheaders.h" #include "llagent.h" -#include "llfloatercall.h" #include "llfloaterreg.h" #include "llimview.h" #include "llnotifications.h" @@ -446,6 +445,17 @@ void LLVoiceChannel::resume() } } +boost::signals2::connection LLVoiceChannel::setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb, bool at_front) +{ + if (at_front) + { + return sCurrentVoiceChannelChangedSignal.connect(cb, boost::signals2::at_front); + } + else + { + return sCurrentVoiceChannelChangedSignal.connect(cb); + } +} // // LLVoiceChannelGroup diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index 77801142cb..cb86671305 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -64,7 +64,7 @@ public: typedef boost::function<void(const LLUUID& session_id)> channel_changed_callback_t; typedef boost::signals2::signal<void(const LLUUID& session_id)> channel_changed_signal_t; static channel_changed_signal_t sCurrentVoiceChannelChangedSignal; - static boost::signals2::connection setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb) { return sCurrentVoiceChannelChangedSignal.connect(cb); } + static boost::signals2::connection setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb, bool at_front = false); LLVoiceChannel(const LLUUID& session_id, const std::string& session_name); diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index cfa1f05ec0..c2d26a1971 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -4443,6 +4443,33 @@ void LLVoiceClient::participantUpdatedEvent( participant->mPower = 0.0f; } participant->mVolume = volume; + + + // *HACH: mantipov: added while working on EXT-3544 + /* + Sometimes LLVoiceClient::participantUpdatedEvent callback is called BEFORE + LLViewerChatterBoxSessionAgentListUpdates::post() sometimes AFTER. + + participantUpdatedEvent updates voice participant state in particular participantState::mIsModeratorMuted + Originally we wanted to update session Speaker Manager to fire LLSpeakerVoiceModerationEvent to fix the EXT-3544 bug. + Calling of the LLSpeakerMgr::update() method was added into LLIMMgr::processAgentListUpdates. + + But in case participantUpdatedEvent() is called after LLViewerChatterBoxSessionAgentListUpdates::post() + voice participant mIsModeratorMuted is changed after speakers are updated in Speaker Manager + and event is not fired. + + So, we have to call LLSpeakerMgr::update() here. In any case it is better than call it + in LLCallFloater::draw() + */ + LLVoiceChannel* voice_cnl = LLVoiceChannel::getCurrentVoiceChannel(); + if (voice_cnl) + { + LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(voice_cnl->getSessionID()); + if (speaker_manager) + { + speaker_manager->update(true); + } + } } else { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index f98aa361e0..70bfc67523 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -134,9 +134,21 @@ public: virtual F64 getMediaInterest() const { - F64 tmp = mObject->getTotalMediaInterest(); - return (tmp < 0.0) ? mObject->getPixelArea() : tmp; + F64 interest = mObject->getTotalMediaInterest(); + if (interest < (F64)0.0) + { + // media interest not valid yet, try pixel area + interest = mObject->getPixelArea(); + // HACK: force recalculation of pixel area if interest is the "magic default" of 1024. + if (interest == 1024.f) + { + const_cast<LLVOVolume*>(static_cast<LLVOVolume*>(mObject))->setPixelAreaAndAngle(gAgent); + interest = mObject->getPixelArea(); + } + } + return interest; } + virtual bool isInterestingEnough() const { return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest()); diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index f8bb7336db..7866f735c5 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -38,10 +38,12 @@ // Library includes #include "llwindow.h" // spawnWebBrowser() +#include "llagent.h" #include "llappviewer.h" #include "llfloatermediabrowser.h" #include "llfloaterreg.h" #include "lllogininstance.h" +#include "llparcel.h" #include "llsd.h" #include "lltoastalertpanel.h" #include "llui.h" @@ -49,6 +51,8 @@ #include "llversioninfo.h" #include "llviewercontrol.h" #include "llviewernetwork.h" +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" #include "llviewerwindow.h" class URLLoader : public LLToastAlertPanel::URLLoader @@ -144,7 +148,27 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url, substitution["LANGUAGE"] = LLUI::getLanguage(); substitution["GRID"] = LLViewerLogin::getInstance()->getGridLabel(); substitution["OS"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple(); + substitution["SESSION_ID"] = gAgent.getSessionID(); + // find the region ID + LLUUID region_id; + LLViewerRegion *region = gAgent.getRegion(); + if (region) + { + region_id = region->getRegionID(); + } + substitution["REGION_ID"] = region_id; + + // find the parcel ID + LLUUID parcel_id; + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (parcel) + { + parcel_id = parcel->getID(); + } + substitution["PARCEL_ID"] = parcel_id; + + // expand all of the substitution strings and escape the url std::string expanded_url = url; LLStringUtil::format(expanded_url, substitution); diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index e6857ea780..1940d65ae4 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -334,7 +334,6 @@ void LLWorldMapView::draw() gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setColorMask(true, true); -#if 1 // Draw the image tiles drawMipmap(width, height); gGL.flush(); @@ -452,7 +451,7 @@ void LLWorldMapView::draw() // Draw the region name in the lower left corner if (sMapScale >= DRAW_TEXT_THRESHOLD) { - LLFontGL* font = LLFontGL::getFontSansSerifSmall(); + LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Small", LLFontGL::BOLD)); std::string mesg; if (info->isDown()) { @@ -468,14 +467,13 @@ void LLWorldMapView::draw() mesg, 0, llfloor(left + 3), llfloor(bottom + 2), LLColor4::white, - LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); + LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW); } } } - #endif - #if 1 + // Draw background rectangle LLGLSUIDefault gls_ui; { @@ -566,7 +564,7 @@ void LLWorldMapView::draw() drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, getString("Loading"), ""); } } - #endif + // turn off the scissor LLGLDisable no_scissor(GL_SCISSOR_TEST); diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp index 9897f40c4e..1cdccd2baa 100644 --- a/indra/newview/llworldmipmap.cpp +++ b/indra/newview/llworldmipmap.cpp @@ -186,9 +186,8 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 grid_y, S32 level) { // Get the grid coordinates -// std::string imageurl = llformat("http://map.secondlife.com.s3.amazonaws.com/%d/%05d/%05d/map-%d-%d-%d-objects.jpg", std::string imageurl = llformat("http://map.secondlife.com.s3.amazonaws.com/map-%d-%d-%d-objects.jpg", - level, grid_x, grid_y, level, grid_x, grid_y); + level, grid_x, grid_y); // DO NOT COMMIT!! DEBUG ONLY!!! // Use a local jpeg for every tile to test map speed without S3 access diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 73b5222ee3..4f4fc83819 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6352,7 +6352,8 @@ void LLPipeline::renderDeferredLighting() mDeferredLight[0].flush(); - if (gSavedSettings.getBOOL("RenderDeferredBlurLight")) + if (gSavedSettings.getBOOL("RenderDeferredBlurLight") && + gSavedSettings.getBOOL("RenderDeferredGI")) { LLFastTimer ftm(FTM_EDGE_DETECTION); //get edge map diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 88e77f11ee..cb511c2f0b 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -71,10 +71,14 @@ <color name="Transparent" value="0 0 0 0" /> + <!-- Make potentially unused colors show up bright purple. + Leave this here until all Unused? are removed below, otherwise + the viewer generates many warnings on startup. --> + <color + name="Unused?" + value="1 0 1 1" /> - - - <!-- UI Definitions --> + <!-- UI Definitions --> <color name="AgentChatColor" @@ -98,6 +102,24 @@ name="AvatarNameColor" reference="White" /> <color + name="AvatarListItemIconDefaultColor" + reference="White" /> + <color + name="AvatarListItemIconOnlineColor" + reference="White" /> + <color + name="AvatarListItemIconOfflineColor" + value="0.5 0.5 0.5 0.5" /> + <color + name="AvatarListItemIconVoiceInvitedColor" + reference="AvatarListItemIconOfflineColor" /> + <color + name="AvatarListItemIconVoiceJoinedColor" + reference="AvatarListItemIconOnlineColor" /> + <color + name="AvatarListItemIconVoiceLeftColor" + reference="AvatarListItemIconOfflineColor" /> + <color name="BackgroundChatColor" reference="DkGray_66" /> <color diff --git a/indra/newview/skins/default/textures/icons/Parcel_Damage_Light_Alt.png b/indra/newview/skins/default/textures/icons/Parcel_Damage_Light_Alt.png Binary files differnew file mode 100644 index 0000000000..d72f02f708 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Parcel_Damage_Light_Alt.png diff --git a/indra/newview/skins/default/textures/icons/SL_Logo.png b/indra/newview/skins/default/textures/icons/SL_Logo.png Binary files differnew file mode 100644 index 0000000000..c9fbde987a --- /dev/null +++ b/indra/newview/skins/default/textures/icons/SL_Logo.png diff --git a/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg b/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg Binary files differnew file mode 100644 index 0000000000..3bb7f7183c --- /dev/null +++ b/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 412f8b6d68..cc87d5c105 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -70,6 +70,8 @@ with the same filename but different name <texture name="Audio_Over" file_name="icons/Audio_Over.png" preload="false" /> <texture name="Audio_Press" file_name="icons/Audio_Press.png" preload="false" /> + <texture name="Avaline_Icon" file_name="icons/avaline_default_icon.jpg" preload="true" /> + <texture name="BackArrow_Disabled" file_name="icons/BackArrow_Disabled.png" preload="false" /> <texture name="BackArrow_Off" file_name="icons/BackArrow_Off.png" preload="false" /> <texture name="BackArrow_Press" file_name="icons/BackArrow_Press.png" preload="false" /> @@ -170,6 +172,7 @@ with the same filename but different name <texture name="ForwardArrow_Press" file_name="icons/ForwardArrow_Press.png" preload="false" /> <texture name="Generic_Group" file_name="icons/Generic_Group.png" preload="false" /> + <texture name="icon_group.tga" file_name="icons/Generic_Group.png" preload="false" /> <texture name="Generic_Group_Large" file_name="icons/Generic_Group_Large.png" preload="false" /> <texture name="Generic_Object_Medium" file_name="icons/Generic_Object_Medium.png" preload="false" /> <texture name="Generic_Object_Small" file_name="icons/Generic_Object_Small.png" preload="false" /> @@ -234,6 +237,7 @@ with the same filename but different name <texture name="Inv_Gloves" file_name="icons/Inv_Gloves.png" preload="false" /> <texture name="Inv_Hair" file_name="icons/Inv_Hair.png" preload="false" /> <texture name="Inv_LinkItem" file_name="icons/Inv_LinkItem.png" preload="false" /> + <texture name="Inv_LinkItem_Broken" file_name="icons/Inv_LinkItem_Broken.png" preload="false" /> <texture name="Inv_LinkFolder" file_name="icons/Inv_LinkFolder.png" preload="false" /> <texture name="Inv_Jacket" file_name="icons/Inv_Jacket.png" preload="false" /> <texture name="Inv_LookFolderOpen" file_name="icons/Inv_LookFolderOpen.png" preload="false" /> @@ -311,6 +315,9 @@ with the same filename but different name <texture name="Notices_Unread" file_name="bottomtray/Notices_Unread.png" preload="true" /> + <texture name="NoEntryLines" file_name="world/NoEntryLines.png" use_mips="true" preload="false" /> + <texture name="NoEntryPassLines" file_name="world/NoEntryPassLines.png" use_mips="true" preload="false" /> + <texture name="Object_Cone" file_name="build/Object_Cone.png" preload="false" /> <texture name="Object_Cube" file_name="build/Object_Cube.png" preload="false" /> <texture name="Object_Cylinder" file_name="build/Object_Cylinder.png" preload="false" /> @@ -487,7 +494,8 @@ with the same filename but different name <texture name="SliderThumb_Off" file_name="widgets/SliderThumb_Off.png" /> <texture name="SliderThumb_Disabled" file_name="widgets/SliderThumb_Disabled.png" /> <texture name="SliderThumb_Press" file_name="widgets/SliderThumb_Press.png" /> - <texture name="SL_Logo" file_name="map_infohub.tga" /> + + <texture name="SL_Logo" file_name="icons/SL_Logo.png" preload="true" /> <texture name="Snapshot_Off" file_name="bottomtray/Snapshot_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" /> <texture name="Snapshot_Over" file_name="bottomtray/Snapshot_Over.png" preload="false" /> @@ -495,12 +503,12 @@ with the same filename but different name <texture name="startup_logo" file_name="windows/startup_logo.png" preload="true" /> - <texture name="Stepper_Down_Disabled" file_name="widgets/Stepper_Down_Disabled.png" preload="true" /> - <texture name="Stepper_Down_Off" file_name="widgets/Stepper_Down_Off.png" preload="true" /> - <texture name="Stepper_Down_Press" file_name="widgets/Stepper_Down_Press.png" preload="true" /> - <texture name="Stepper_Up_Disabled" file_name="widgets/Stepper_Up_Disabled.png" preload="true" /> - <texture name="Stepper_Up_Off" file_name="widgets/Stepper_Up_Off.png" preload="true" /> - <texture name="Stepper_Up_Press" file_name="widgets/Stepper_Up_Press.png" preload="true" /> + <texture name="Stepper_Down_Disabled" file_name="widgets/Stepper_Down_Disabled.png" preload="false" /> + <texture name="Stepper_Down_Off" file_name="widgets/Stepper_Down_Off.png" preload="false" /> + <texture name="Stepper_Down_Press" file_name="widgets/Stepper_Down_Press.png" preload="false" /> + <texture name="Stepper_Up_Disabled" file_name="widgets/Stepper_Up_Disabled.png" preload="false" /> + <texture name="Stepper_Up_Off" file_name="widgets/Stepper_Up_Off.png" preload="false" /> + <texture name="Stepper_Up_Press" file_name="widgets/Stepper_Up_Press.png" preload="false" /> <texture name="Stop_Off" file_name="icons/Stop_Off.png" preload="false" /> <texture name="Stop_Over" file_name="icons/Stop_Over.png" preload="false" /> @@ -549,8 +557,8 @@ with the same filename but different name <texture name="TabTop_Right_Selected" file_name="containers/TabTop_Right_Selected.png" preload="false" /> <texture name="TabTop_Middle_Off" file_name="containers/TabTop_Middle_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9" /> <texture name="TabTop_Middle_Selected" file_name="containers/TabTop_Middle_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9" /> - <texture name="TabTop_Left_Off" file_name="containers/TabTop_Left_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9" /> - <texture name="TabTop_Left_Selected" file_name="containers/TabTop_Left_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9" /> + <texture name="TabTop_Left_Off" file_name="containers/TabTop_Left_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9" /> + <texture name="TabTop_Left_Selected" file_name="containers/TabTop_Left_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9" /> <texture name="TaskPanel_Tab_Off" file_name="taskpanel/TaskPanel_Tab_Off.png" preload="false" scale.left="4" scale.top="29" scale.right="36" scale.bottom="4" /> <texture name="TaskPanel_Tab_Selected" file_name="taskpanel/TaskPanel_Tab_Selected.png" preload="false" scale.left="5" scale.top="30" scale.right="36" scale.bottom="5" /> @@ -570,6 +578,8 @@ with the same filename but different name <texture name="Toast_CloseBtn" file_name="windows/Toast_CloseBtn.png" preload="true" /> <texture name="Toast_Background" file_name="windows/Toast_Background.png" preload="true" scale.left="4" scale.top="28" scale.right="60" scale.bottom="4" /> + <texture name="Toast_Over" file_name="windows/Toast_Over.png" preload="true" + scale.left="4" scale.top="28" scale.right="60" scale.bottom="4" /> <texture name="Tool_Create" file_name="build/Tool_Create.png" preload="false" /> <texture name="Tool_Dozer" file_name="build/Tool_Dozer.png" preload="false" /> @@ -635,28 +645,12 @@ with the same filename but different name <texture name="PowerOff_Over" file_name="icons/PowerOff_Over.png" preload="false" /> <texture name="PowerOff_Press" file_name="icons/PowerOff_Press.png" preload="false" /> - <!--WARNING OLD ART *do not use*--> - - <texture name="btn_chatbar.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0" /> - <texture name="btn_chatbar_selected.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0" /> - - <texture name="cam_rotate_out.tga" preload="false" /> - <texture name="cam_rotate_in.tga" preload="false" /> - <texture name="cam_zoom_out.tga" preload="false" /> - <texture name="cam_zoom_plus_in.tga" preload="false" /> - <texture name="cam_zoom_minus_in.tga" preload="false" /> - + <!--WARNING OLD ART BELOW *do not use*--> <texture name="icn_chatbar.tga" /> - <texture name="icn_media-pause.tga" /> - <texture name="icn_media-play.tga" /> - <texture name="icn_music-play.tga" /> - <texture name="icn_music-pause.tga" /> <texture name="icn_media_web.tga" preload="true" /> <texture name="icn_media_movie.tga" preload="true" /> - <texture name="icn_speaker-muted_dark.tga" /> <texture name="icn_speaker_dark.tga" /> - <texture name="icn_voice-localchat.tga" /> <texture name="icn_voice-groupfocus.tga" /> <texture name="icn_voice-pvtfocus.tga" /> @@ -666,67 +660,30 @@ with the same filename but different name <texture name="jump_right_out.tga" /> <texture name="jump_right_in.tga" /> - <texture name="move_forward_out.tga" preload="false" /> - <texture name="move_forward_in.tga" preload="false" /> - <texture name="move_left_out.tga" preload="false" /> - <texture name="move_left_in.tga" preload="false" /> - <texture name="move_turn_left_out.tga" preload="false" /> - <texture name="move_turn_left_in.tga" preload="false" /> - <texture name="move_turn_right_out.tga" preload="false" /> - <texture name="move_turn_right_in.tga" preload="false" /> - <texture name="move_right_out.tga" preload="false" /> - <texture name="move_right_in.tga" preload="false" /> - <texture name="move_up_in.tga" preload="false" /> - <texture name="move_up_out.tga" preload="false" /> - <texture name="move_down_in.tga" preload="false" /> - <texture name="move_down_out.tga" preload="false" /> - <texture name="up_arrow.tga" file_name="up_arrow.png" /> <texture name="down_arrow.tga" file_name="down_arrow.png" /> + <texture name="arrow_down.tga" /> <texture name="tearoffbox.tga" /> <texture name="tearoff_pressed.tga" /> <texture name="icn_label_music.tga" /> <texture name="icn_label_media.tga" /> - <texture name="arrow_down.tga" /> - <texture name="cloud-particle.j2c" use_mips="true" /> - - <texture name="skin_thumbnail_default.png" preload="false" /> - - <texture name="icn_textfield_enabled.tga" scale.left="5" scale.top="5" scale.bottom="5" scale.right="5" /> <texture name="icn_rounded-text-field.tga" scale.left="14" scale.bottom="16" scale.top="16" scale.right="114" /> - <texture name="toolbar_btn_enabled.tga" scale.left="7" scale.top="32" scale.right="121" scale.bottom="0" /> - <texture name="toolbar_btn_disabled.tga" scale.left="7" scale.top="32" scale.right="121" scale.bottom="0" /> - <texture name="toolbar_btn_selected.tga" scale.left="7" scale.top="32" scale.right="121" scale.bottom="0" /> - <texture name="toggle_button_off" file_name="toggle_button_off.png" preload="true" /> <texture name="toggle_button_selected" file_name="toggle_button_selected.png" preload="true" /> <texture name="sm_rounded_corners_simple.tga" scale.left="4" scale.top="4" scale.bottom="4" scale.right="4" /> - <texture name="rounded_square.tga" file_name="rounded_square.j2c" preload="true" scale.left="16" scale.top="16" scale.right="112" scale.bottom="16" /> - - <texture name="rounded_square_soft.tga" file_name="rounded_square_soft.j2c" preload="true" scale.left="16" scale.top="16" scale.right="112" scale.bottom="16" /> - - <texture name="toolbar_tab.tga" preload="true" scale.left="6" scale.top="42" scale.right="104" scale.bottom="8" /> - <texture name="toolbar_bg.tga" preload="true" scale.left="6" scale.top="42" scale.right="96" scale.bottom="16" /> - - <texture name="tab_top_blue.tga" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9" /> - <texture name="tab_top_selected_blue.tga" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9" /> - <texture name="color_swatch_alpha.tga" preload="true" /> <texture name="button_anim_pause.tga" /> <texture name="button_anim_pause_selected.tga" /> <texture name="button_anim_play.tga" /> <texture name="button_anim_play_selected.tga" /> - <texture name="button_anim_stop.tga" /> - <texture name="button_anim_stop_selected.tga" /> <texture name="crosshairs.tga" /> <texture name="direction_arrow.tga" /> - <texture name="foot_shadow.j2c" use_mips="true" /> <texture name="icon_auction.tga" /> <texture name="icon_avatar_offline.tga" /> @@ -736,10 +693,6 @@ with the same filename but different name <texture name="icon_event.tga" /> <texture name="icon_event_mature.tga" /> <texture name="icon_for_sale.tga" /> - <texture name="icon_group.tga" /> - <texture name="icon_groupnotice.tga" /> - <texture name="icon_groupnoticeinventory.tga" /> - <texture name="icon_place.tga" /> <texture name="icon_place_for_sale.tga" /> <texture name="icon_popular.tga" /> <texture name="icon_top_pick.tga" /> @@ -762,8 +715,6 @@ with the same filename but different name <texture name="media_icon.tga" file_name="icn_label_media.tga" /> <texture name="music_icon.tga" file_name="icn_label_music.tga" /> - <texture name="NoEntryLines" file_name="world/NoEntryLines.png" use_mips="true" preload="false" /> - <texture name="NoEntryPassLines" file_name="world/NoEntryPassLines.png" use_mips="true" preload="false" /> <texture name="notify_tip_icon.tga" /> <texture name="notify_caution_icon.tga" /> @@ -773,13 +724,11 @@ with the same filename but different name <texture name="pixiesmall.j2c" use_mips="true" /> <texture name="script_error.j2c" use_mips="true" /> <texture name="silhouette.j2c" use_mips="true" /> + <texture name="foot_shadow.j2c" use_mips="true" /> + <texture name="cloud-particle.j2c" use_mips="true" /> <texture name="status_no_build.tga" /> <texture name="status_voice.tga" /> - <texture name="status_buy_currency.tga" /> - <texture name="status_buy_currency_pressed.tga" /> - <texture name="status_buy_land.tga" /> - <texture name="status_buy_land_pressed.tga" /> <texture name="status_no_fly.tga" /> <texture name="status_health.tga" /> <texture name="status_no_push.tga" /> @@ -806,23 +755,5 @@ with the same filename but different name <texture name="default_profile_picture.j2c" /> <texture name="locked_image.j2c" /> - <texture name="media_btn_back.png" /> - <texture name="media_btn_done.png" /> - <texture name="media_btn_forward.png" /> - <texture name="media_btn_home.png" /> - <texture name="media_btn_newwindow.png" /> - <texture name="media_btn_optimalzoom.png" /> - <texture name="media_btn_reload.png" /> - <texture name="media_btn_scrolldown.png" /> - <texture name="media_btn_scrollleft.png" /> - <texture name="media_btn_scrollright.png" /> - <texture name="media_btn_scrollup.png" /> - <texture name="media_btn_stoploading.png" /> - <texture name="media_panel_divider.png" /> - <texture name="media_floater_border_16.png" scale_top="12" scale_left="4" scale_bottom="4" scale_right="12" /> - - <texture name="media_panel_bg.png" preload="true" scale_left="9" scale_top="9" scale_right="9" scale_bottom="9" /> - <texture name="media_panel_hoverrectangle.png" preload="true" scale_left="9" scale_top="9" scale_right="9" scale_bottom="9" /> - </textures> diff --git a/indra/newview/skins/default/xui/en/favorites_bar_button.xml b/indra/newview/skins/default/xui/en/favorites_bar_button.xml index 361f5a7bc8..90105f92fd 100644 --- a/indra/newview/skins/default/xui/en/favorites_bar_button.xml +++ b/indra/newview/skins/default/xui/en/favorites_bar_button.xml @@ -3,6 +3,7 @@ <!-- All buttons in the Favorites bar will be created from this one --> <button follows="left|bottom" + font_halign="center" halign="center" height="15" image_disabled="transparent.j2c" @@ -14,10 +15,16 @@ image_pressed="Favorite_Link_Over" image_pressed_selected="Favorite_Link_Over" hover_glow_amount="0.15" + label_shadow="false" layout="topleft" left="0" name="favorites_bar_btn" + pad_bottom="-1" + pad_left="11" + pad_right="7" tab_stop="false" + pad_right="10" + pad_left="10" top="0" use_ellipses="true" - width="120" /> + width="140" /> diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml index 6956b73371..cb4cbd229a 100644 --- a/indra/newview/skins/default/xui/en/floater_aaa.xml +++ b/indra/newview/skins/default/xui/en/floater_aaa.xml @@ -15,21 +15,21 @@ title="TEST FLOATER" save_dock_state="true" save_visibility="true" - single_instance="true" + single_instance="true" width="320"> <string name="nudge_parabuild">Nudge 1</string> <string name="test_the_vlt">This string is extracted.</string> <chat_history allow_html="true" bg_readonly_color="ChatHistoryBgColor" - bg_writeable_color="ChatHistoryBgColor" - border_visible="false" + bg_writeable_color="ChatHistoryBgColor" + border_visible="false" follows="all" font="SansSerif" - left="1" + left="1" top="20" layout="topleft" - height="260" + height="260" name="chat_history" parse_highlights="true" text_color="ChatHistoryTextColor" 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 81e6503407..cc955369e2 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -4,6 +4,7 @@ height="420" layout="topleft" name="floaterland" + help_topic="floaterland" save_rect="true" title="ABOUT LAND" width="490"> @@ -274,7 +275,7 @@ <button enabled="false" follows="left|top" - height="23S" + height="23" label="Deed" layout="topleft" left_pad="2" @@ -472,6 +473,16 @@ top="328" width="100" /> <button + enabled="true" + follows="left|top" + height="23" + label="Script Info" + layout="topleft" + left="10" + name="Scripts..." + top="352" + width="100" /> + <button enabled="false" follows="left|top" height="23" diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml index 153a9c2c45..0dc7d62b19 100644 --- a/indra/newview/skins/default/xui/en/floater_customize.xml +++ b/indra/newview/skins/default/xui/en/floater_customize.xml @@ -12,16 +12,6 @@ title="APPEARANCE" top_delta="-185" width="524"> - <check_box - enabled="true" - height="23" - label="Show Attachments in Previews" - layout="topleft" - left="110" - name="show attachments" - tool_tip="Display attachments on your avatar in the preview panels below." - top="20" - width="146" /> <tab_container height="517" layout="topleft" @@ -55,6 +45,7 @@ label="Shape" layout="topleft" name="Shape" + help_topic="customize_shape_tab" width="400"> <icon follows="top|right" @@ -340,6 +331,7 @@ scratch and wear it. label="Skin" layout="topleft" name="Skin" + help_topic="customize_skin_tab" width="400"> <icon follows="top|right" @@ -591,6 +583,7 @@ scratch and wear it. label="Hair" layout="topleft" name="Hair" + help_topic="customize_hair_tab" width="400"> <icon follows="top|right" @@ -812,6 +805,7 @@ scratch and wear it. layout="topleft" left_delta="0" name="Eyes" + help_topic="customize_eyes_tab" top_delta="0" width="389"> <icon @@ -1010,6 +1004,7 @@ scratch and wear it. layout="topleft" left_delta="0" name="Shirt" + help_topic="customize_shirt_tab" top_delta="0" width="389"> <icon @@ -1215,6 +1210,7 @@ scratch and wear it. layout="topleft" left_delta="0" name="Pants" + help_topic="customize_pants_tab" top_delta="0" width="389"> <icon @@ -1420,6 +1416,7 @@ scratch and wear it. layout="topleft" left_delta="0" name="Shoes" + help_topic="customize_shoes_tab" top_delta="0" width="389"> <icon @@ -1625,6 +1622,7 @@ scratch and wear it. layout="topleft" left_delta="0" name="Socks" + help_topic="customize_socks_tab" top_delta="0" width="389"> <icon @@ -1830,6 +1828,7 @@ scratch and wear it. layout="topleft" left_delta="0" name="Jacket" + help_topic="customize_jacket_tab" top_delta="0" width="389"> <icon @@ -2047,6 +2046,7 @@ scratch and wear it. layout="topleft" left_delta="0" name="Gloves" + help_topic="customize_gloves_tab" top_delta="0" width="389"> <icon @@ -2252,6 +2252,7 @@ scratch and wear it. layout="topleft" left_delta="0" name="Undershirt" + help_topic="customize_undershirt_tab" top_delta="0" width="389"> <icon @@ -2457,6 +2458,7 @@ scratch and wear it. layout="topleft" left_delta="0" name="Underpants" + help_topic="customize_underpants_tab" top_delta="0" width="389"> <icon @@ -2662,6 +2664,7 @@ scratch and wear it. layout="topleft" left_delta="0" name="Skirt" + help_topic="customize_skirt_tab" top_delta="0" width="389"> <icon @@ -2867,6 +2870,7 @@ scratch and wear it. layout="topleft" left_delta="0" name="Alpha" + help_topic="customize_alpha_tab" top_delta="0" width="389"> <icon @@ -3154,6 +3158,7 @@ scratch and wear it. layout="topleft" left_delta="0" name="Tattoo" + help_topic="customize_tattoo_tab" top_delta="0" width="389"> <icon @@ -3381,6 +3386,16 @@ scratch and wear it. </scroll_container> <button bottom="598" + follows="right|left" + height="20" + label="Script Info" + label_selected="Script Info" + layout="topleft" + name="script_info" + left="2" + width="98" /> + <button + bottom="598" follows="right|bottom" height="23" label="Make Outfit" 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 81c54ae55e..1d67123726 100644 --- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml +++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml @@ -11,6 +11,10 @@ title="UNKNOWN PERSON IS CALLING" width="410"> <floater.string + name="lifetime"> + 5 + </floater.string> + <floater.string name="localchat"> Nearby Voice Chat </floater.string> @@ -39,6 +43,13 @@ left_delta="19" top="35" width="36" /> + <group_icon + enabled="false" + follows="left|top" + height="36" + layout="topleft" + top="35" + width="36" /> <text clip_partial="true" font="SansSerifLarge" diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml index fb8893678d..920f0c909a 100644 --- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml @@ -16,8 +16,10 @@ can_dock="true" bevel_style="in" height="300" + min_width="150" layout="topleft" name="nearby_chat" + help_topic="nearby_chat" save_rect="true" title="NEARBY CHAT" save_dock_state="true" diff --git a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml index c6bc093c6c..eb772cc0bd 100644 --- a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml +++ b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml @@ -11,6 +11,10 @@ title="CALLING" width="410"> <floater.string + name="lifetime"> + 5 + </floater.string> + <floater.string name="localchat"> Nearby Voice Chat </floater.string> @@ -35,6 +39,13 @@ left_delta="19" top="35" width="36" /> + <group_icon + enabled="false" + follows="left|top" + height="36" + layout="topleft" + top="35" + width="36" /> <text font="SansSerifLarge" height="20" diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml index 2f26e5d0c1..15655a920e 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences.xml @@ -7,6 +7,7 @@ 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 abc30c335c..0d155fb01e 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_texture.xml @@ -4,13 +4,13 @@ auto_tile="true" can_resize="true" follows="left|top" - height="313" + height="350" layout="topleft" - min_height="120" - min_width="320" + min_height="200" + min_width="370" name="preview_texture" help_topic="preview_texture" - width="320"> + width="370"> <floater.string name="Title"> Texture: [NAME] @@ -64,7 +64,7 @@ height="16" layout="topleft" left_delta="-110" - name="dimensions" + name="aspect_ratio" top_pad="5" width="200"> Preview aspect ratio @@ -112,7 +112,7 @@ label="OK" layout="topleft" left="6" - name="keep" + name="Keep" top_pad="5" width="100" /> <button @@ -121,7 +121,7 @@ label="Cancel" layout="topleft" left_pad="5" - name="discard" + name="Discard" top_delta="0" width="100" /> <button diff --git a/indra/newview/skins/default/xui/en/floater_script_limits.xml b/indra/newview/skins/default/xui/en/floater_script_limits.xml new file mode 100644 index 0000000000..98c44ad1b3 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_script_limits.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + height="570" + help_topic="scriptlimits" + layout="topleft" + name="scriptlimits" + save_rect="true" + title="SCRIPT INFORMATION" + width="480"> + <tab_container + bottom="555" + follows="left|right|top|bottom" + layout="topleft" + left="1" + name="scriptlimits_panels" + right="-1" + tab_position="top" + top="20" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_search.xml b/indra/newview/skins/default/xui/en/floater_search.xml index 9c1a5499db..5a9e2ebe6e 100644 --- a/indra/newview/skins/default/xui/en/floater_search.xml +++ b/indra/newview/skins/default/xui/en/floater_search.xml @@ -4,8 +4,8 @@ can_resize="true" height="646" layout="topleft" - min_height="140" - min_width="467" + min_height="646" + min_width="670" name="floater_search" help_topic="floater_search" save_rect="true" diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index ec54522d3e..a36a1b591b 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -9,6 +9,7 @@ name="Snapshot" help_topic="snapshot" save_rect="true" + save_visibility="true" title="SNAPSHOT PREVIEW" width="215"> <floater.string 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 474b703ae5..1fa613468f 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -5,7 +5,7 @@ can_close="false" height="270" layout="topleft" - min_height="146" + min_height="122" min_width="190" name="floater_voice_controls" title="Voice Controls" @@ -32,6 +32,10 @@ name="no_one_near"> No one near </string> + <string + name="max_visible_items"> + 5 + </string> <panel bevel_style="out" border="true" @@ -83,14 +87,58 @@ visible="true" width="20" /> </panel> - <button - follows="left|right|top" - height="24" - label="Leave Call" - left="91" - name="leave_call_btn" - top_pad="6" - width="100" /> + <layout_stack + border_size="0" + clip="false" + follows="all" + height="28" + layout="topleft" + left="10" + mouse_opaque="false" + name="leave_call_stack" + orientation="horizontal" + top_pad="5" + width="263"> + <layout_panel + auto_resize="true" + follows="left|right" + height="26" + layout="topleft" + min_height="23" + min_width="5" + mouse_opaque="false" + name="left_anchor" + width="80"/> + <layout_panel + auto_resize="false" + follows="left|right" + height="26" + layout="topleft" + mouse_opaque="false" + min_height="24" + min_width="100" + name="leave_call_btn_panel" + width="100"> + <button + follows="left|right" + height="24" + label="Leave Call" + left="0" + name="leave_call_btn" + top="0" + width="100" /> + </layout_panel> + <layout_panel + auto_resize="true" + follows="left|right" + height="26" + layout="topleft" + mouse_opaque="false" + min_height="24" + min_width="5" + name="right_anchor" + width="80"/> + </layout_stack> </panel> <avatar_list follows="all" diff --git a/indra/newview/skins/default/xui/en/floater_water.xml b/indra/newview/skins/default/xui/en/floater_water.xml index 7f31692ad9..32739ac953 100644 --- a/indra/newview/skins/default/xui/en/floater_water.xml +++ b/indra/newview/skins/default/xui/en/floater_water.xml @@ -4,6 +4,7 @@ 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/floater_window_size.xml b/indra/newview/skins/default/xui/en/floater_window_size.xml new file mode 100644 index 0000000000..355d257785 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_window_size.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_minimize="false" + can_resize="false" + height="105" + layout="topleft" + name="window_size" + title="WINDOW SIZE" + width="205"> + <string name="resolution_format">[RES_X] x [RES_Y]</string> + <text + follows="top|left" + font="SansSerif" + height="16" + left="15" + top="10" + name="windowsize_text" + width="280"> + Set window size: + </text> + <combo_box + allow_text_entry="true" + height="23" + follows="left|top" + left_delta="0" + max_chars="20" + name="window_size_combo" + tool_tip="width x height" + top_pad="5" + width="179"> + <combo_box.item + label="1000 x 700 (default)" + name="item0" + value="1000 x 700" /> + <combo_box.item + label="1024 x 768" + name="item1" + value="1024 x 768" /> + <combo_box.item + label="1280 x 720 (720p)" + name="item2" + value="1280 x 720" /> + <combo_box.item + label="1920 x 1080 (1080p)" + name="item3" + value="1920 x 1080" /> + </combo_box> + <button + follows="right|bottom" + height="23" + label="Set" + left_delta="0" + name="set_btn" + top_pad="10" + width="85" /> + <button + follows="right|bottom" + height="23" + label="Cancel" + left_pad="5" + name="cancel_btn" + top_delta="0" + width="85" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index e632b67d11..8904d4f49c 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -296,7 +296,7 @@ layout="topleft" name="pg_label" width="60"> - PG + General </text> <check_box @@ -330,7 +330,7 @@ layout="topleft" name="mature_label" width="66"> - Mature + Moderate </text> <check_box @@ -361,7 +361,7 @@ top_delta="2" left_pad="3" layout="topleft" - name="pg_label" + name="adult_label" width="66"> Adult </text> @@ -480,7 +480,10 @@ name="location" select_on_focus="true" tool_tip="Type the name of a region" - width="152" /> + width="152"> + <search_editor.commit_callback + function="WMap.Location" /> + </search_editor> <button follows="top|right" height="23" diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index 996d0f1b72..2f2964c42b 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -54,7 +54,7 @@ width="175" use_ellipses="true" /> <text - follows="all" + follows="left|top|right" height="35" left="8" name="user_details" diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml index 65a545d2ed..861eb9009a 100644 --- a/indra/newview/skins/default/xui/en/main_view.xml +++ b/indra/newview/skins/default/xui/en/main_view.xml @@ -15,7 +15,7 @@ orientation="vertical" top="19"> <layout_panel auto_resize="false" - height="65" + height="60" mouse_opaque="false" name="nav_bar_container" width="1024" diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 7a0b11872a..690167bc33 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -233,6 +233,13 @@ parameter="RegInClient" /> </menu_item_check> <menu_item_separator /> + <menu_item_call + label="Set Window Size..." + name="Set Window Size..."> + <menu_item_call.on_click + function="Floater.Show" + parameter="window_size" /> + </menu_item_call> <menu_item_call label="Show TOS" name="TOS"> 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 faf33bd1b1..31263fbea8 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_list.xml @@ -2,7 +2,29 @@ <context_menu layout="topleft" name="Participant List Context Menu"> - <menu_item_call + <menu_item_check + label="Sort by Name" + layout="topleft" + name="SortByName"> + <menu_item_check.on_click + function="ParticipantList.Sort" + parameter="sort_by_name" /> + <menu_item_check.on_check + function="ParticipantList.CheckItem" + parameter="is_sorted_by_name" /> + </menu_item_check> + <menu_item_check + label="Sort by Recent Speakers" + layout="topleft" + name="SortByRecentSpeakers"> + <menu_item_check.on_click + function="ParticipantList.Sort" + parameter="sort_by_recent_speakers" /> + <menu_item_check.on_check + function="ParticipantList.CheckItem" + parameter="is_sorted_by_recent_speakers" /> + </menu_item_check> + <menu_item_call label="View Profile" layout="topleft" name="View Profile"> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups.xml b/indra/newview/skins/default/xui/en/menu_people_groups.xml new file mode 100644 index 0000000000..afa680139d --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_groups.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<menu name="menu_group_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false"> + <menu_item_call + label="View Info" + name="View Info"> + <menu_item_call.on_click + function="People.Groups.Action" + parameter="view_info" /> + <menu_item_call.on_enable + function="People.Groups.Enable" + parameter="view_info" /> + </menu_item_call> + <menu_item_call + label="Chat" + name="Chat"> + <menu_item_call.on_click + function="People.Groups.Action" + parameter="chat" /> + <menu_item_call.on_enable + function="People.Groups.Enable" + parameter="chat" /> + </menu_item_call> + <menu_item_call + label="Call" + name="Call"> + <menu_item_call.on_click + function="People.Groups.Action" + parameter="call" /> + <menu_item_call.on_enable + function="People.Groups.Enable" + parameter="call" /> + </menu_item_call> + <menu_item_separator /> + <menu_item_call + label="Activate" + name="Activate"> + <menu_item_call.on_click + function="People.Groups.Action" + parameter="activate" /> + <menu_item_call.on_enable + function="People.Groups.Enable" + parameter="activate" /> + </menu_item_call> + <menu_item_separator /> + <menu_item_call + label="Leave" + name="Leave"> + <menu_item_call.on_click + function="People.Groups.Action" + parameter="leave" /> + <menu_item_call.on_enable + function="People.Groups.Enable" + parameter="leave" /> + </menu_item_call> +</menu> diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml index c849188699..9b3948b29b 100644 --- a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml +++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml @@ -104,6 +104,9 @@ <on_click function="Places.LandmarksGear.Folding.Action" parameter="expand_all" /> + <on_enable + function="Places.LandmarksGear.Enable" + parameter="expand_all" /> </menu_item_call> <menu_item_call label="Collapse all folders" @@ -112,6 +115,9 @@ <on_click function="Places.LandmarksGear.Folding.Action" parameter="collapse_all" /> + <on_enable + function="Places.LandmarksGear.Enable" + parameter="collapse_all" /> </menu_item_call> <menu_item_check label="Sort by Date" diff --git a/indra/newview/skins/default/xui/en/menu_profile_overflow.xml b/indra/newview/skins/default/xui/en/menu_profile_overflow.xml index d0128d1c9a..1dc1c610cf 100644 --- a/indra/newview/skins/default/xui/en/menu_profile_overflow.xml +++ b/indra/newview/skins/default/xui/en/menu_profile_overflow.xml @@ -19,4 +19,40 @@ <menu_item_call.on_click function="Profile.Share" /> </menu_item_call> + <menu_item_call + label="Kick" + layout="topleft" + name="kick"> + <menu_item_call.on_click + function="Profile.Kick" /> + <menu_item_call.on_visible + function="Profile.EnableGod" /> + </menu_item_call> + <menu_item_call + label="Freeze" + layout="topleft" + name="freeze"> + <menu_item_call.on_click + function="Profile.Freeze" /> + <menu_item_call.on_visible + function="Profile.EnableGod" /> + </menu_item_call> + <menu_item_call + label="Unfreeze" + layout="topleft" + name="unfreeze"> + <menu_item_call.on_click + function="Profile.Unfreeze" /> + <menu_item_call.on_visible + function="Profile.EnableGod" /> + </menu_item_call> + <menu_item_call + label="CSR" + layout="topleft" + name="csr"> + <menu_item_call.on_click + function="Profile.CSR" /> + <menu_item_call.on_visible + function="Profile.EnableGod" /> + </menu_item_call> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml index 6768d7fccb..134b331514 100644 --- a/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml @@ -13,12 +13,18 @@ name="Expand all folders"> <menu_item_call.on_click function="TeleportHistory.ExpandAllFolders" /> + <on_enable + function="TeleportHistory.GearMenu.Enable" + parameter="expand_all" /> </menu_item_call> <menu_item_call label="Collapse all folders" name="Collapse all folders"> <menu_item_call.on_click function="TeleportHistory.CollapseAllFolders" /> + <on_enable + function="TeleportHistory.GearMenu.Enable" + parameter="collapse_all" /> </menu_item_call> <menu_item_separator layout="topleft" /> <menu_item_call diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b4ce32ea1d..4e495bab3f 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1119,6 +1119,13 @@ <menu_item_call.on_click function="View.DefaultUISize" /> </menu_item_call> + <menu_item_call + label="Set Window Size..." + name="Set Window Size..."> + <menu_item_call.on_click + function="Floater.Show" + parameter="window_size" /> + </menu_item_call> <menu_item_separator/> <menu_item_check label="Limit Select Distance" @@ -2481,30 +2488,30 @@ name="Debug Pipeline"> <menu_item_check.on_check function="CheckControl" - parameter="RenderDebugGL" /> + parameter="RenderDebugPipeline" /> <menu_item_check.on_click function="ToggleControl" - parameter="RenderDebugGL" /> + parameter="RenderDebugPipeline" /> </menu_item_check> <menu_item_check label="Fast Alpha" name="Fast Alpha"> <menu_item_check.on_check function="CheckControl" - parameter="RenderDebugGL" /> + parameter="RenderFastAlpha" /> <menu_item_check.on_click function="ToggleControl" - parameter="RenderDebugGL" /> + parameter="RenderFastAlpha" /> </menu_item_check> <menu_item_check label="Animation Textures" name="Animation Textures"> <menu_item_check.on_check function="CheckControl" - parameter="RenderDebugGL" /> + parameter="AnimateTextures" /> <menu_item_check.on_click function="ToggleControl" - parameter="RenderDebugGL" /> + parameter="AnimateTextures" /> </menu_item_check> <menu_item_check label="Disable Textures" @@ -2555,7 +2562,7 @@ function="CheckControl" parameter="RenderAttachedLights" /> <menu_item_check.on_click - function="Advanced.HandleAttchedLightParticles" + function="Advanced.HandleAttachedLightParticles" parameter="RenderAttachedLights" /> </menu_item_check> <menu_item_check @@ -2565,7 +2572,7 @@ function="CheckControl" parameter="RenderAttachedParticles" /> <menu_item_check.on_click - function="Advanced.HandleAttchedLightParticles" + function="Advanced.HandleAttachedLightParticles" parameter="RenderAttachedParticles" /> </menu_item_check> <menu_item_check @@ -2975,14 +2982,6 @@ <menu_item_call.on_click function="Advanced.SendTestIMs" /> </menu_item_call> - <menu_item_call - label="Test Inspectors" - name="Test Inspectors" - shortcut="control|shift|I"> - <menu_item_call.on_click - function="Floater.Show" - parameter="test_inspectors" /> - </menu_item_call> </menu> <menu create_jump_keys="true" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index d4b712e048..95a7374e7b 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4498,14 +4498,14 @@ You don't have permission to copy this. <notification icon="notifytip.tga" name="InventoryAccepted" - type="offer"> + type="notifytip"> [NAME] received your inventory offer. </notification> <notification icon="notifytip.tga" name="InventoryDeclined" - type="offer"> + type="notifytip"> [NAME] declined your inventory offer. </notification> @@ -5022,9 +5022,9 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [O [ITEM_SLURL] <form name="form"> <button - index="0" - name="Keep" - text="Keep"/> + index="4" + name="Show" + text="Show"/> <button index="1" name="Discard" @@ -5106,7 +5106,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [O <notification icon="notify.tga" name="OfferFriendship" - type="offer"> + type="alertmodal"> [NAME] is offering friendship. [MESSAGE] @@ -5121,6 +5121,10 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [O index="1" name="Decline" text="Decline"/> + <button + index="2" + name="Send IM" + text="Send IM"/> </form> </notification> diff --git a/indra/newview/skins/default/xui/en/panel_bars.xml b/indra/newview/skins/default/xui/en/panel_bars.xml index 527ec4e007..96722ce278 100644 --- a/indra/newview/skins/default/xui/en/panel_bars.xml +++ b/indra/newview/skins/default/xui/en/panel_bars.xml @@ -9,7 +9,7 @@ width="1024"> <layout_stack name="menu_stack" orientation="vertical" height="768" border_size="0"> <panel auto_resize="false" width="1024" name="status_bar" filename="panel_status_bar.xml"/> - <panel auto_resize="false" width="1024" height="65" name="navigation bar" filename="panel_navigation_bar.xml"/> + <panel auto_resize="false" width="1024" height="60" name="navigation bar" filename="panel_navigation_bar.xml"/> <layout_stack name="hud_stack" orientation="horizontal" auto_resize="true" width="1024" height="500" follows="all"> <panel auto_resize="true" name="floater_view" height="500"/> <panel auto_resize="false" filename="panel_side_tray.xml" height="500" width="333"/> diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 3e2910458f..b92aa10ffc 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -47,7 +47,7 @@ min_height="23" width="310" top="4" - min_width="192" + min_width="188" name="chat_bar" user_resize="false" filename="panel_nearby_chat_bar.xml" /> @@ -88,9 +88,9 @@ layout="topleft" left="0" name="DUMMY" - min_width="4" + min_width="3" top="0" - width="4"/> + width="3"/> <layout_panel mouse_opaque="false" auto_resize="false" @@ -126,10 +126,10 @@ image_name="spacer24.tga" layout="topleft" left="0" - min_width="4" + min_width="3" name="DUMMY" top="0" - width="4"/> + width="3"/> <layout_panel mouse_opaque="false" auto_resize="false" @@ -168,10 +168,10 @@ image_name="spacer24.tga" layout="topleft" left="0" - min_width="4" + min_width="3" name="DUMMY" top="0" - width="4"/> + width="3"/> <layout_panel mouse_opaque="false" auto_resize="false" @@ -211,10 +211,10 @@ image_name="spacer24.tga" layout="topleft" left="0" - min_width="4" + min_width="3" name="DUMMY" top="0" - width="4"/> + width="3"/> <layout_panel mouse_opaque="false" auto_resize="false" @@ -227,16 +227,20 @@ <button follows="left|right" height="23" + image_selected="PushButton_Selected_Press" + image_pressed="PushButton_Press" + image_pressed_selected="PushButton_Selected_Press" left="0" label="" layout="topleft" name="snapshots" width="36" top="4" + is_toggle="true" image_overlay="Snapshot_Off" tool_tip="Take snapshot"> - <button.commit_callback - function="Floater.Toggle" + <button.init_callback + function="Button.SetFloaterToggle" parameter="snapshot" /> </button> </layout_panel> @@ -248,7 +252,7 @@ top="0" name="chiclet_list_panel" width="189" - min_width="180" + min_width="110" user_resize="false" auto_resize="true"> <!--*NOTE: min_width of the chiclet_panel (chiclet_list) must be the same @@ -259,7 +263,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. height="23" layout="topleft" left="1" - min_width="180" + min_width="110" name="chiclet_list" top="6" chiclet_padding="4" @@ -327,6 +331,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. min_width="35" user_resize="false"> <chiclet_im_well + max_displayed_count="99" flash_period="0.3" follows="right" height="23" @@ -336,7 +341,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. top="4" width="35"> <!-- -Emulate 4 states of button by background images, see detains in EXT-3147. The same should be for notification_well button +Emulate 4 states of button by background images, see details 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 @@ -356,10 +361,10 @@ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well image_selected="PushButton_Selected_Press" label_color="Black" left="0" - max_displayed_count="99" name="Unread IM messages" pad_left="0" pad_right="0" + tool_tip="Conversations" width="35" > <button.init_callback function="Button.SetDockableFloaterToggle" @@ -374,7 +379,7 @@ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well layout="topleft" min_height="28" top="0" - left_pad="4" + left_pad="3" name="notification_well_panel" width="35" min_width="35" @@ -405,6 +410,7 @@ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well image_overlay="Notices_Unread" image_overlay_alignment="center" pad_right="5" + tool_tip="Notifications" width="35" > <button.init_callback function="Button.SetDockableFloaterToggle" diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml index 859822dd81..39c4923f12 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_header.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml @@ -28,7 +28,7 @@ height="12" layout="topleft" left_pad="5" - right="-60" + right="-120" name="user_name" text_color="white" bg_readonly_color="black" @@ -46,5 +46,5 @@ right="-5" top="8" value="23:30" - width="50" /> + width="110" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml index b5760e977f..1fbf7abda9 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml @@ -103,6 +103,7 @@ top_pad="2" max_length="63" name="classified_name" + prevalidate_callback="ascii" text_color="black" width="290" /> <text diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml index bbf86089cb..be3c0bbd96 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml @@ -293,7 +293,7 @@ right="-10" name="partner_edit_link" value="[[URL] Edit]" - width="150" /> + width="50" /> <panel follows="left|top|right" height="15" diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml index 9f06e64560..67a4edbf32 100644 --- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml +++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml @@ -228,8 +228,17 @@ top_pad="10" value="Title:" width="290" /> + <text + follows="left|top" + height="22" + layout="topleft" + left="0" + name="title_value" + text_color="white" + top_pad="5" + use_ellipses="true" + width="290" /> <line_editor - background_image_disabled="task_panel_background.png" follows="left|top|right" height="22" layout="topleft" @@ -238,7 +247,7 @@ name="title_editor" prevalidate_callback="ascii" text_readonly_color="white" - top_pad="5" + top_delta="0" width="290" /> <text follows="left|top" diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index 1f211c0fed..c899dcb750 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -23,7 +23,7 @@ layout="topleft" name="tab_favorites" title="Favorites bar"> - <inventory_subtree_panel + <places_inventory_panel allow_multi_select="true" border="true" bottom="0" @@ -39,7 +39,7 @@ layout="topleft" name="tab_landmarks" title="Landmarks"> - <inventory_subtree_panel + <places_inventory_panel allow_multi_select="true" border="true" bottom="0" @@ -55,7 +55,7 @@ layout="topleft" name="tab_inventory" title="My Inventory"> - <inventory_subtree_panel + <places_inventory_panel allow_multi_select="true" border="true" bottom="0" @@ -71,7 +71,7 @@ layout="topleft" name="tab_library" title="Library"> - <inventory_subtree_panel + <places_inventory_panel allow_multi_select="true" border="true" bottom="0" 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 4353b306cd..58437cd4d2 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -208,7 +208,7 @@ halign="center" layout="topleft" name="Reset Current"> <menu_item_call.on_click - function="Inventory.ResetFilter" /> + function="Inventory.ResetFilters" /> </menu_item_call> <menu_item_call label="Close All Folders" diff --git a/indra/newview/skins/default/xui/en/panel_my_profile.xml b/indra/newview/skins/default/xui/en/panel_my_profile.xml index d51893793c..10381d3987 100644 --- a/indra/newview/skins/default/xui/en/panel_my_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_my_profile.xml @@ -37,7 +37,7 @@ height="485" layout="topleft" name="profile_scroll" - reserve_scroll_corner="true" + reserve_scroll_corner="false" opaque="true" top="0" width="313"> @@ -48,7 +48,7 @@ layout="topleft" top="0" left="0" - width="313"> + width="297"> <panel follows="left|top" height="117" diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index 74265a51ca..0f9b095d8c 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -4,7 +4,7 @@ background_visible="true" bg_opaque_color="MouseGray" follows="left|top|right" - height="65" + height="60" layout="topleft" name="navigation_bar" chrome="true" @@ -18,7 +18,7 @@ visible="true" left="0" top="0" - height="65" + height="60" width="600"/> <icon follows="all" @@ -29,7 +29,7 @@ visible="false" left="0" top="0" - height="65" + height="60" width="600"/> <panel background_visible="false" @@ -149,13 +149,13 @@ <favorites_bar follows="left|right|top" - font="SansSerif" + font="SansSerifSmall" height="15" layout="topleft" left="0" name="favorite" image_drag_indication="arrow_down.tga" - bottom="62" + bottom="57" width="590"> <chevron_button name=">>" image_unselected="TabIcon_Close_Off" diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml index 2543656a8b..f09a0e03ed 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml @@ -9,7 +9,7 @@ top="21" width="310"> <string name="min_width"> - 192 + 188 </string> <string name="max_width"> 320 @@ -21,14 +21,14 @@ height="23" label="Click here to chat." layout="topleft" - left_delta="7" + left_delta="3" text_pad_right="25" left="0" max_length="512" name="chat_box" tool_tip="Press Enter to say, Ctrl+Enter to shout" top="1" - width="279" /> + width="283" /> <output_monitor auto_update="true" follows="right" 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 5c99022f35..7e512f9594 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -3,7 +3,7 @@ <panel name="Outfits" background_visible="true" follows="all" - height="550" + height="570" label="Things" layout="topleft" min_height="350" @@ -21,19 +21,6 @@ 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" - 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" @@ -46,6 +33,19 @@ mouse_opaque="true" name="cof_accordionpanel" start_folder="Current Outfit" /> + <inventory_panel + label="MY OUTFITS" + help_topic="my_outfits_tab" + allow_multi_select="true" + follows="all" + border="false" + left="0" + top="0" + height="500" + width="290" + mouse_opaque="true" + name="outfitslist_accordionpanel" + start_folder="My Outfits" /> </tab_container> <panel background_visible="true" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 8883c27c47..08a10553a8 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -411,5 +411,15 @@ background_visible="true" name="chat_btn" tool_tip="Open chat session" width="110" /> + <button + follows="bottom|left" + top="4" + left_pad="2" + height="23" + label="Group Call" + layout="topleft" + name="group_call_btn" + tool_tip="Call this group" + width="110" /> </panel> </panel> 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 426a2b1f9e..17651b8caa 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -10,10 +10,6 @@ name="advanced" top="1" width="517"> - <panel.string - name="resolution_format"> - [RES_X] x [RES_Y] - </panel.string> <panel.string name="aspect_ratio_text"> [NUM]:[DEN] 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 41bd7f3dcc..c98555735a 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -329,10 +329,9 @@ text_readonly_color="LabelDisabledColor" bg_writeable_color="LtGray" use_ellipses="false" - bg_visible="false" - border_visible="false" + bg_visible="true" + border_visible="true" hover="false" - text_color="LabelTextColor" commit_on_focus_lost = "true" follows="left|top" height="50" 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 83dc7cd854..34bd6fb091 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -98,12 +98,12 @@ decimal_digits="0" follows="left|top" height="15" - increment="10" - initial_value="50" + increment="100" + initial_value="500" layout="topleft" left_delta="150" - max_val="1500" - min_val="50" + max_val="10000" + min_val="100" name="max_bandwidth" top_delta="0" width="180" /> 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 b14089c3a2..677d0de243 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 @@ -29,12 +29,14 @@ height="75" layout="topleft" left="0" + mouse_opaque="false" orientation="horizontal" top="100"> <!-- outer layout_panels center the inner one --> <layout_panel name="left_bookend" width="0" + mouse_opaque="false" layout="topleft" user_resize="false" /> <layout_panel @@ -42,6 +44,7 @@ auto_resize="false" user_resize="false" layout="topleft" + mouse_opaque="false" min_width="22" width="22" top="4"> @@ -263,10 +266,12 @@ width="38" right="-2" top="-1" + mouse_opaque="false" orientation="horizontal"> <layout_panel layout="topleft" width="16" + mouse_opaque="false" auto_resize="false" user_resize="false"> <icon @@ -282,6 +287,7 @@ <layout_panel layout="topleft" width="16" + mouse_opaque="false" auto_resize="false" user_resize="false"> <icon diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml b/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml new file mode 100644 index 0000000000..d98f690339 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + border="true" + follows="top|left" + height="570" + label="MY AVATAR" + layout="topleft" + left="0" + name="script_limits_my_avatar_panel" + top="0" + width="480"> + <text + type="string" + length="1" + follows="left|top" + height="20" + layout="topleft" + left="10" + name="loading_text" + top="10" + text_color="EmphasisColor" + width="480"> + Loading... + </text> + <scroll_list + draw_heading="true" + follows="all" + height="500" + layout="topleft" + left_delta="0" + multi_select="true" + name="scripts_list" + top_delta="17" + width="460"> + <scroll_list.columns + label="Size (kb)" + name="size" + width="70" /> + <scroll_list.columns + label="URLs" + name="urls" + width="50" /> + <scroll_list.columns + label="Object Name" + name="name" + width="140" /> + <scroll_list.columns + label="Location" + name="location" + width="130" /> + </scroll_list> + <button + follows="bottom|left" + height="19" + label="Refresh List" + layout="bottomleft" + left_pad="5" + name="refresh_list_btn" + top="34" + left="10" + width="100" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml new file mode 100644 index 0000000000..0fa3c1cf2e --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + border="true" + follows="top|left" + height="570" + label="REGION MEMORY" + layout="topleft" + name="script_limits_region_memory_panel" + top="0" + left="0" + width="480"> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="10" + name="script_memory" + top_pad="24" + text_color="White" + width="480"> + Parcel Script Memory + </text> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="30" + name="parcels_listed" + top_delta="18" + visible="true" + width="480"> + Parcels Owned: + </text> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="30" + name="memory_used" + top_delta="18" + width="480"> + Memory used: + </text> + <text + type="string" + length="1" + follows="left|top" + height="20" + layout="topleft" + left="10" + name="loading_text" + top_delta="32" + text_color="EmphasisColor" + width="480"> + Loading... + </text> + <scroll_list + draw_heading="true" + follows="all" + height="409" + layout="topleft" + left_delta="0" + multi_select="true" + name="scripts_list" + top_delta="16" + width="460"> + <scroll_list.columns + label="Size (kb)" + name="size" + width="70" /> + <scroll_list.columns + label="Object Name" + name="name" + width="100" /> + <scroll_list.columns + label="Object Owner" + name="owner" + width="100" /> + <scroll_list.columns + label="Parcel / Location" + name="location" + width="130" /> +<!-- <scroll_list.commit_callback + function="TopObjects.CommitObjectsList" />--> + </scroll_list> + <button + follows="bottom|left" + height="19" + label="Refresh List" + layout="bottomleft" + left_pad="5" + name="refresh_list_btn" + top="34" + left="10" + width="100" /> + <button + follows="bottom|right" + height="19" + visible="false" + label="Highlight" + layout="bottomright" + left="370" + name="highlight_btn" + top="34" + width="100" /> + <button + follows="bottom|right" + height="19" + visible="false" + label="Return" + layout="bottomright" + name="return_btn" + top="34" + left_delta="-105" + width="100" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index 63b7112c17..61f0fa3099 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml @@ -31,6 +31,24 @@ </sidetray_tab> <sidetray_tab + name="sidebar_me" + help_topic="sidebar_me" + tab_title="My Profile" + description="Edit your public profile and Picks." + image="TabIcon_Me_Off" + image_selected="TabIcon_Me_Selected" + mouse_opaque="false" + background_visible="true" + > + <panel + class="panel_me" + name="panel_me" + filename="panel_me.xml" + label="Me" + /> + </sidetray_tab> + + <sidetray_tab name="sidebar_people" help_topic="sidebar_people" tab_title="People" @@ -42,6 +60,7 @@ > <panel_container name="panel_container" + default_panel_name="panel_people" width="333" > <panel @@ -93,20 +112,21 @@ </sidetray_tab> <sidetray_tab - name="sidebar_me" - help_topic="sidebar_me" - tab_title="My Profile" - description="Edit your public profile and Picks." - image="TabIcon_Me_Off" - image_selected="TabIcon_Me_Selected" + name="sidebar_inventory" + help_topic="sidebar_inventory" + tab_title="My Inventory" + description="Browse your inventory." + image="TabIcon_Things_Off" + image_selected="TabIcon_Things_Selected" mouse_opaque="false" background_visible="true" > <panel - class="panel_me" - name="panel_me" - filename="panel_me.xml" - label="Me" + class="sidepanel_inventory" + name="sidepanel_inventory" + filename="sidepanel_inventory.xml" + label="Edit Inventory" + font="SansSerifBold" /> </sidetray_tab> @@ -129,23 +149,4 @@ /> </sidetray_tab> - <sidetray_tab - name="sidebar_inventory" - help_topic="sidebar_inventory" - tab_title="My Inventory" - description="Browse your inventory." - image="TabIcon_Things_Off" - image_selected="TabIcon_Things_Selected" - mouse_opaque="false" - background_visible="true" - > - <panel - class="sidepanel_inventory" - name="sidepanel_inventory" - filename="sidepanel_inventory.xml" - label="Edit Inventory" - font="SansSerifBold" - /> - </sidetray_tab> - </side_tray> diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index 57b090e5b4..3578c4326d 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -80,16 +80,6 @@ name="volume_btn" tool_tip="Global Volume Control" width="16" /> - <panel - class="panel_volume_pulldown" - follows="all" - height="533" - layout="topleft" - left="0" - name="volume_pulldown" - top="5" - visible="false" - width="313" /> <text enabled="true" diff --git a/indra/newview/skins/default/xui/en/panel_toast.xml b/indra/newview/skins/default/xui/en/panel_toast.xml index 707b24c92c..ba2d61afb7 100644 --- a/indra/newview/skins/default/xui/en/panel_toast.xml +++ b/indra/newview/skins/default/xui/en/panel_toast.xml @@ -14,7 +14,7 @@ left="0" top="0" follows="right|bottom" - bg_opaque_image="Toast_Background" + bg_opaque_image="Toast_Over" bg_alpha_image="Toast_Background" can_minimize="false" can_tear_off="false" diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml index 7f4b4aef82..44248eedd5 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -2,23 +2,24 @@ <panel background_visible="true" follows="all" -height="635" +height="570" label="Outfits" layout="topleft" -min_height="460" +min_height="350" +min_width="240" name="appearance panel" top="0" left="0" - width="333"> +width="333"> <string name="No Outfit" value="No Outfit" /> <panel left="0" top="0" - follows="left|top|right" + follows="all" layout="topleft" - width="333" + width="330" height="33" name="panel_currentlook" > @@ -85,9 +86,9 @@ left="0" class="panel_outfits_inventory" filename="panel_outfits_inventory.xml" name="panel_outfits_inventory" - height="550" - min_height="510" - width="333" + height="515" + min_height="410" + width="320" top_pad="0" follows="all" /> 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 7b0b4b0bde..4a992dadd9 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml @@ -33,10 +33,10 @@ height="18" image_name="Lock" layout="topleft" - right="-50" + right="-15" mouse_opaque="true" name="IconLocked" - top="4" + top="8" width="18" /> <button follows="top|right" @@ -60,14 +60,23 @@ use_ellipses="true" value="Object Profile" width="275" /> + <text + follows="top|left" + height="13" + layout="topleft" + left="45" + name="where" + text_color="LtGray_50" + value="(Inventory)" + width="150" /> <panel follows="all" - height="500" + height="490" label="" layout="topleft" left="10" help_topic="" - top="30" + top="45" width="313" background_visible="true" bg_alpha_color="DkGray2"> @@ -125,7 +134,7 @@ layout="topleft" left="5" name="LabelCreatorTitle" -top_pad="10" + top_pad="10" width="78"> Creator: </text> @@ -135,12 +144,12 @@ top_pad="10" default_icon_name="Generic_Person" layout="topleft" left_pad="0" - top_delta="-6" + top_delta="-6" mouse_opaque="true" width="20" /> <text type="string" - follows="left|right" + follows="left|right|top" font="SansSerifSmall" height="15" layout="topleft" @@ -165,28 +174,28 @@ top_pad="10" follows="left|top" height="23" layout="topleft" - left="5" + left="5" name="LabelOwnerTitle" -top_pad="5" + top_pad="10" width="78"> Owner: </text> <avatar_icon - follows="top|left" - height="20" - default_icon_name="Generic_Person" - layout="topleft" - left_pad="0" - top_delta="-6" - mouse_opaque="true" - width="20" /> + follows="top|left" + height="20" + default_icon_name="Generic_Person" + layout="topleft" + left_pad="0" + top_delta="-6" + mouse_opaque="true" + width="20" /> <text type="string" - follows="left|right" - font="SansSerifSmall" - height="15" - layout="topleft" - left_pad="5" + follows="left|right|top" + font="SansSerifSmall" + height="15" + layout="topleft" + left_pad="5" name="LabelOwnerName" top_delta="6" width="140"> @@ -224,7 +233,7 @@ top_pad="10" top_delta="0" width="222"> Wed May 24 12:50:46 2006 - </text> + </text> <panel border="false" follows="left|top" @@ -350,7 +359,7 @@ top_pad="10" tool_tip="Next owner can give away or resell this object" width="106" /> </panel> - <check_box + <check_box height="18" label="For Sale" layout="topleft" @@ -388,144 +397,21 @@ top_pad="10" height="23" max_val="999999999" top_pad="10"/> - <!--line_editor - border_style="line" - border_thickness="1" - follows="left|top|right" - height="16" - layout="topleft" - left_pad="5" - max_length="25" - name="EditPrice" - top_delta="0" - width="242" /--> - <!--text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="10" - name="BaseMaskDebug" - top="155" - width="330"> - B: - </text> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="60" - name="OwnerMaskDebug" - top_delta="0" - width="270"> - O: - </text> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="60" - name="GroupMaskDebug" - top_delta="0" - width="210"> - G: - </text> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="60" - name="EveryoneMaskDebug" - top_delta="0" - width="150"> - E: - </text> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="60" - name="NextMaskDebug" - top_delta="0" - width="90"> - N: - </text--> - <!--text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="10" - name="SaleLabel" - top_pad="5" - width="330"> - Mark Item: - </text--> - <!--radio_group - draw_border="false" - follows="left|top|right" - height="16" - layout="topleft" - left_delta="78" - name="RadioSaleType" - top_delta="0" - width="252"> - <radio_item - height="16" - label="Original" - layout="topleft" - left="0" - name="radio" - top="0" - width="70" /> - <radio_item - height="16" - label="Copy" - layout="topleft" - left_delta="60" - name="radio2" - top_delta="0" - width="70" /> - </radio_group--> - <!--text - type="string" - length="1" - follows="left|top" - height="16" - layout="topleft" - left="10" - name="TextPrice" - top_pad="5" - width="78"> - Price: L$ - </text--> - </panel> + </panel> <panel - height="25" + height="30" layout="bottomright" help_topic="button_tab" name="button_panel" left="5" - bottom="5" + bottom="2" width="313"> <button - follows="bottom|right" - height="25" + height="23" label="Cancel" layout="topleft" name="cancel_btn" right="-1" - left_pad="10" width="100" /> - </panel> -</panel> + </panel> + </panel>
\ No newline at end of file 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 5b379b54e3..d26e855e2f 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -6,7 +6,7 @@ name="object properties" help_topic="object_properties" save_rect="true" - title="Object Properties" + title="Object Profile" width="333"> <panel.string name="text deed continued"> @@ -57,127 +57,173 @@ Mixed Sale </panel.string> <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="SansSerifHuge" + height="26" + layout="topleft" + left_pad="10" + name="title" + text_color="LtGray" + top="0" + use_ellipses="true" + value="Object Profile" + width="275" /> + <text + follows="top|left" + height="13" + layout="topleft" + left="45" + name="where" + text_color="LtGray_50" + value="(In World)" + width="150" /> <panel follows="all" - height="500" + height="490" label="" layout="topleft" - left="5" + left="10" help_topic="" - top="30" - border="1" - width="313"> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="10" + top="45" + width="313" + background_visible="true" + bg_alpha_color="DkGray2"> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="5" name="Name:" - top_pad="5" - width="90"> - Name: - </text> - <line_editor - follows="left|top|right" - height="19" - layout="topleft" - left_pad="0" - max_length="63" + top="10" + width="78"> + Name: + </text> + <line_editor + border_style="line" + border_thickness="1" + follows="left|top|right" + height="20" + layout="topleft" + left_delta="78" + max_length="63" name="Object Name" - select_on_focus="true" - top_delta="0" - width="170" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="10" + top_delta="0" + width="225" /> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="5" name="Description:" - top_pad="3" - width="90"> - Description: - </text> + top_pad="10" + width="78"> + Description: + </text> <line_editor + border_style="line" + border_thickness="1" follows="left|top|right" - height="19" + height="23" layout="topleft" - left_pad="0" - max_length="127" name="Object Description" select_on_focus="true" - top_delta="0" - width="170" /> - <text - type="string" - left="10" - length="1" - follows="left|top" - height="19" - layout="topleft" - name="Creator:" - width="90"> - Creator: - </text> - <text - type="string" - length="1" - follows="left|top" - left_pad="0" - height="19" - layout="topleft" + left_delta="78" + max_length="127" + top_delta="-5" + width="225"/> + <text + type="string" + length="1" + follows="left|top" + height="23" + layout="topleft" + left="5" + name="CreatorNameLabel" + top_pad="10" + width="78"> + Creator: + </text> + <avatar_icon + follows="top|left" + height="20" + default_icon_name="Generic_Person" + layout="topleft" + left_pad="0" + top_delta="-6" + mouse_opaque="true" + width="20" /> + <text + type="string" + follows="left|right" + font="SansSerifSmall" + height="15" + layout="topleft" + left_pad="5" name="Creator Name" - width="175"> - Esbee Linden - </text> - <text - type="string" - length="1" - left="10" - follows="left|top" - height="19" - layout="topleft" - name="Owner:" - width="90"> - Owner: - </text> - <text - type="string" - length="1" - follows="left|top" - height="19" - layout="topleft" - name="Owner Name" - left_pad="0" - width="175"> - Erica Linden - </text> - <text - type="string" - length="1" - follows="left|top" - layout="topleft" - left="10" - height="18" - name="Group:" - top_pad="4" - width="75"> - Group: - </text> - <button + top_delta="6" + width="140"> + Erica Linden + </text> + <text + type="string" + length="1" + follows="left|top" + height="23" + layout="topleft" + left="5" + name="Owner:" + top_pad="10" + width="78"> + Owner: + </text> + <avatar_icon + follows="top|left" + height="20" + default_icon_name="Generic_Person" + layout="topleft" + left_pad="0" + top_delta="-6" + mouse_opaque="true" + width="20" /> + <text + type="string" + follows="left|right" + font="SansSerifSmall" + height="15" + layout="topleft" + left_pad="5" + name="Owner Name" + top_delta="6" + width="140"> + Erica Linden + </text> + <text + type="string" + length="1" + follows="left|top" + height="23" + layout="topleft" + left="5" + name="Group_label" + top_pad="10" + width="78"> + Group: + </text> + <button follows="top|left" height="10" image_disabled="Activate_Checkmark" @@ -203,43 +249,34 @@ width="150" /> <button follows="top|left" - height="20" + height="23" label="Deed" label_selected="Deed" layout="topleft" name="button deed" top_pad="0" - left="100" + left="81" tool_tip="Deeding gives this item away with next owner permissions. Group shared objects can be deeded by a group officer." - width="80" /> - <check_box - height="19" - follows="left|top" - label="Share" - layout="topleft" - name="checkbox share with group" - tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions." - left_pad="3" width="100" /> <text type="string" length="1" follows="left|top" - height="16" + height="9" layout="topleft" - top_pad="15" - left="10" + top_pad="5" + left="5" name="label click action" - width="90"> + width="280"> Click to: </text> <combo_box follows="left|top" - height="20" + height="23" layout="topleft" name="clickaction" width="168" - left_pad="0"> + left="81"> <combo_box.item label="Touch (default)" name="Touch/grab(default)" @@ -261,26 +298,131 @@ name="Open" value="Open" /> </combo_box> - <check_box - height="16" + <panel + border="false" + follows="left|top" + layout="topleft" + mouse_opaque="false" + background_visible="true" + bg_alpha_color="DkGray" + name="perms_inv" + left="0" + top_pad="15" + height="135" + width="313"> + <text + type="string" + length="1" + left="10" top_pad="15" - label="For Sale:" + text_color="EmphasisColor" + height="15" + follows="left|top|right" + layout="topleft" + name="perm_modify" + width="200"> + You can modify this object + </text> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="10" + name="Anyone can:" + top_pad="8" + width="100"> + Anyone: + </text> + <check_box + height="18" + label="Copy" + layout="topleft" + left_pad="0" + name="checkbox allow everyone copy" + top_delta="-2" + width="90" /> + <check_box + height="18" + label="Move" layout="topleft" + name="checkbox allow everyone move" + left_pad="0" + width="150" /> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="10" + name="GroupLabel" + top_pad="8" + width="100"> + Group: + </text> + <check_box + height="18" + label="Share" + layout="topleft" + left_pad="90" + top_delta="-2" + name="checkbox share with group" + tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions." + width="150" /> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="10" + name="NextOwnerLabel" + top_pad="8" + width="200" + word_wrap="true"> + Next owner: + </text> + <check_box + height="18" + label="Modify" + layout="topleft" + left="20" + top_pad="0" + name="checkbox next owner can modify" + width="90" /> + <check_box + height="18" + label="Copy" + layout="topleft" + left_pad="0" + name="checkbox next owner can copy" + width="90" /> + <check_box + height="18" + label="Transfer" + layout="topleft" + left_pad="0" + name="checkbox next owner can transfer" + tool_tip="Next owner can give away or resell this object" + width="106" /> + </panel> + <check_box + height="23" + label="For Sale" + layout="topleft" + left="20" name="checkbox for sale" - left="10" - width="90" /> -<!-- NEW SALE TYPE COMBO BOX --> - <combo_box - left_pad="0" - layout="topleft" - follows="left|top" - allow_text_entry="false" - height="20" - intial_value="2" - max_chars="20" - mouse_opaque="true" + top_pad="10" + width="100" /> + <combo_box + height="23" + left_pad="0" + layout="topleft" + follows="left|top" name="sale type" - width="158"> + width="170"> <combo_box.item name="Copy" label="Copy" @@ -293,14 +435,13 @@ name="Original" label="Original" value="1" /> - </combo_box> -<!-- NEW PRICE SPINNER --> - <spinner + </combo_box> + <spinner follows="left|top" decimal_digits="0" increment="1" - top_pad="8" - left="100" + top_pad="10" + left="120" control_name="Edit Cost" name="Edit Cost" label="Price: L$" @@ -310,106 +451,25 @@ height="20" max_val="999999999" /> <check_box - height="15" + height="20" width="110" - top_pad="3" + top_pad="6" label="Show in search" layout="topleft" - left="100" + left="120" name="search_check" tool_tip="Let people see this object in search results" /> - <panel - border="false" - follows="left|top" - layout="topleft" - mouse_opaque="false" - background_visible="true" - bg_alpha_color="DkGray" - name="perms_build" - left="0" - top="241" - height="120" - width="278"> - <text - type="string" - length="1" - left="10" - top_pad="9" - text_color="EmphasisColor" - height="16" - follows="left|top|right" - layout="topleft" - name="perm_modify" - width="250"> - You can modify this object - </text> - <text - type="string" - follows="left|top" - name="Anyone can:" - width="250" - left="10"> - Anyone: - </text> - <check_box - height="19" - label="Move" - layout="topleft" - name="checkbox allow everyone move" - left="15" - width="85" /> - <check_box - height="19" - label="Copy" - layout="topleft" - left_pad="0" - name="checkbox allow everyone copy" - width="90" /> - <text - type="string" - follows="left|top" - height="19" - name="Next owner can:" - width="250" - left="10"> - Next owner: - </text> - <check_box - follows="left|top|right" - label="Modify" - layout="topleft" - left="15" - name="checkbox next owner can modify" - width="85" /> - <check_box - follows="left|top|right" - height="19" - label="Copy" - layout="topleft" - left_pad="0" - name="checkbox next owner can copy" - width="90" /> - <check_box - follows="left|top|right" - height="19" - label="Transfer" - layout="topleft" - name="checkbox next owner can transfer" - left_pad="0" - top_delta="0" - tool_tip="Next owner can give away or resell this object" - width="90" /> <text type="string" text_color="EmphasisColor" length="1" - top_pad="5" + top_pad="15" follows="left|top" layout="topleft" left="10" name="B:" height="10" - width="45"> + width="50"> B: </text> <text @@ -421,7 +481,7 @@ left_pad="0" name="O:" height="10" - width="44"> + width="50"> O: </text> <text @@ -433,7 +493,7 @@ left_pad="0" name="G:" height="10" - width="43"> + width="50"> G: </text> <text @@ -445,7 +505,7 @@ layout="topleft" name="E:" height="10" - width="43"> + width="50"> E: </text> <text @@ -457,7 +517,7 @@ left_pad="0" name="N:" height="10" - width="48"> + width="50"> N: </text> <text @@ -473,7 +533,6 @@ F: </text> </panel> - </panel> <panel height="25" layout="bottomright" @@ -484,30 +543,30 @@ width="313"> <button follows="bottom|left" - height="25" + height="23" label="Open" layout="topleft" left="5" name="open_btn" top="0" - width="60" /> + width="100" /> <button follows="bottom|left" - height="25" + height="23" label="Pay" layout="topleft" left_pad="5" name="pay_btn" top="0" - width="50" /> + width="100" /> <button follows="bottom|left" - height="25" + height="23" label="Buy" layout="topleft" left_pad="5" name="buy_btn" top="0" - width="60" /> + width="100" /> </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 ec4723bd55..447901f984 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2041,6 +2041,59 @@ this texture in your inventory <string name="RegionInfoAllowedResidents">Allowed residents: ([ALLOWEDAGENTS], max [MAXACCESS])</string> <string name="RegionInfoAllowedGroups">Allowed groups: ([ALLOWEDGROUPS], max [MAXACCESS])</string> + <!-- script limits floater --> + <string name="ScriptLimitsParcelScriptMemory">Parcel Script Memory</string> + <string name="ScriptLimitsParcelsOwned">Parcels Listed: [PARCELS]</string> + <string name="ScriptLimitsMemoryUsed">Memory used: [COUNT] kb out of [MAX] kb; [AVAILABLE] kb available</string> + <string name="ScriptLimitsMemoryUsedSimple">Memory used: [COUNT] kb</string> + <string name="ScriptLimitsParcelScriptURLs">Parcel Script URLs</string> + <string name="ScriptLimitsURLsUsed">URLs used: [COUNT] out of [MAX]; [AVAILABLE] available</string> + <string name="ScriptLimitsURLsUsedSimple">URLs used: [COUNT]</string> + <string name="ScriptLimitsRequestError">Error requesting information</string> + <string name="ScriptLimitsRequestWrongRegion">Error: script information is only available in your current region</string> + <string name="ScriptLimitsRequestWaiting">Retrieving information...</string> + <string name="ScriptLimitsRequestDontOwnParcel">You do not have permission to examine this parcel</string> + + <string name="SITTING_ON">Sitting On</string> + <string name="ATTACH_CHEST">Chest</string> + <string name="ATTACH_HEAD">Head</string> + <string name="ATTACH_LSHOULDER">Left Shoulder</string> + <string name="ATTACH_RSHOULDER">Right Shoulder</string> + <string name="ATTACH_LHAND">Left Hand</string> + <string name="ATTACH_RHAND">Right Hand</string> + <string name="ATTACH_LFOOT">Left Foot</string> + <string name="ATTACH_RFOOT">Right Foot</string> + <string name="ATTACH_BACK">Back</string> + <string name="ATTACH_PELVIS">Pelvis</string> + <string name="ATTACH_MOUTH">Mouth</string> + <string name="ATTACH_CHIN">Chin</string> + <string name="ATTACH_LEAR">Left Ear</string> + <string name="ATTACH_REAR">Right Ear</string> + <string name="ATTACH_LEYE">Left Eye</string> + <string name="ATTACH_REYE">Right Eye</string> + <string name="ATTACH_NOSE">Nose</string> + <string name="ATTACH_RUARM">Right Upper Arm</string> + <string name="ATTACH_RLARM">Right Lower Arm</string> + <string name="ATTACH_LUARM">Left Upper Arm</string> + <string name="ATTACH_LLARM">Left Lower Arm</string> + <string name="ATTACH_RHIP">Right Hip</string> + <string name="ATTACH_RULEG">Right Upper Leg</string> + <string name="ATTACH_RLLEG">Right Lower Leg</string> + <string name="ATTACH_LHIP">Left Hip</string> + <string name="ATTACH_LULEG">Left Upper Leg</string> + <string name="ATTACH_LLLEG">Left Lower Leg</string> + <string name="ATTACH_BELLY">Belly</string> + <string name="ATTACH_RPEC">Right Pec</string> + <string name="ATTACH_LPEC">Left Pec</string> + <string name="ATTACH_HUD_CENTER_2">HUD Center 2</string> + <string name="ATTACH_HUD_TOP_RIGHT">HUD Top Right</string> + <string name="ATTACH_HUD_TOP_CENTER">HUD Top Center</string> + <string name="ATTACH_HUD_TOP_LEFT">HUD Top Left</string> + <string name="ATTACH_HUD_CENTER_1">HUD Center 1</string> + <string name="ATTACH_HUD_BOTTOM_LEFT">HUD Bottom Left</string> + <string name="ATTACH_HUD_BOTTOM">HUD Bottom</string> + <string name="ATTACH_HUD_BOTTOM_RIGHT">HUD Bottom Right</string> + <!-- script editor --> <string name="CursorPos">Line [LINE], Column [COLUMN]</string> @@ -2851,13 +2904,13 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="joined_call">Joined the voice call</string> <string name="ringing-im"> - Joining Voice Chat... + Joining voice call... </string> <string name="connected-im"> - Connected, click End Call to hang up + Connected, click Leave Call to hang up </string> <string name="hang_up-im"> - Left Voice Chat + Left voice call </string> <string name="answering-im"> Connecting... @@ -2911,22 +2964,49 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="not_a_mod_error"> You are not a session moderator. </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-3562 issue 'muted' is passed into the gIMMgr::showSessionStartError as a string name. + So, let add string with name="muted" with the same value as "muted_error" --> + <string name="muted"> + A group moderator disabled your text chat. + </string> <string name="muted_error"> A group moderator disabled your text chat. </string> <string name="add_session_event"> Unable to add users to chat session with [RECIPIENT]. </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-3562 issue 'message' is passed into the gIMMgr::showSessionStartError as a string name. + So, let add string with name="message" with the same value as "message_session_event" --> + <string name="message"> + Unable to send your message to the chat session with [RECIPIENT]. + </string> <string name="message_session_event"> Unable to send your message to the chat session with [RECIPIENT]. </string> <string name="mute"> Error while moderating. </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-3459 issue 'removed' is passed into the gIMMgr::showSessionStartError as a string name. + So, let add string with name="removed" with the same value as "removed_from_group" --> + <string name="removed"> + You have been removed from the group. + </string> <string name="removed_from_group"> You have been removed from the group. </string> <string name="close_on_no_ability"> You no longer have the ability to be in the chat session. </string> + <string name="unread_chat_single"> + [SOURCES] has said something new + </string>" + <string name="unread_chat_multiple"> + [SOURCES] have said something new + </string>" </strings> diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml index 2be37d222a..8785dff2ae 100644 --- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml +++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml @@ -11,9 +11,13 @@ top_header_pad="17" bottom_header_pad="10" max_length="2147483647" - enabled="false" track_bottom="true" name="chat_history" type="string" word_wrap="true" - font="SansSerif"/> + font="SansSerif"> + <more_chat_text + mouse_opaque="true" + word_wrap="true" + /> +</chat_history> diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml new file mode 100644 index 0000000000..7cb973f4c8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_im_adhoc + font="SansSerif" + height="25" + name="im_adhoc_chiclet" + show_speaker="false" + width="25"> + <chiclet_im_adhoc.speaker + auto_update="true" + draw_border="false" + height="25" + left="25" + name="speaker" + visible="false" + width="20"/> + <chiclet_im_adhoc.avatar_icon + follows="left|top|bottom" + height="22" + mouse_opaque="true" + name="adhoc_icon" + width="22"/> + <chiclet_im_adhoc.unread_notifications + font="SansSerif" + font_halign="center" + height="25" + left="25" + mouse_opaque="false" + name="unread" + text_color="white" + v_pad="5" + visible="false" + width="20"/> + <chiclet_im_adhoc.new_message_icon + bottom="12" + height="13" + image_name="Unread_IM" + left="12" + name="new_message_icon" + visible="false" + width="13" /> +</chiclet_im_adhoc>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml new file mode 100644 index 0000000000..a9b567225e --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_im_group + font="SansSerif" + height="25" + name="im_group_chiclet" + show_speaker="false" + width="25"> + <chiclet_im_group.speaker + auto_update="true" + draw_border="false" + height="25" + left="25" + name="speaker" + visible="false" + width="20"/> + <chiclet_im_group.group_icon + default_icon="Generic_Group" + follows="left|top|bottom" + height="22" + mouse_opaque="true" + name="group_icon" + width="22"/> + <chiclet_im_group.unread_notifications + height="25" + font="SansSerif" + font_halign="center" + left="25" + mouse_opaque="false" + name="unread" + text_color="white" + v_pad="5" + visible="false" + width="20"/> + <chiclet_im_group.new_message_icon + bottom="12" + height="13" + image_name="Unread_IM" + left="12" + name="new_message_icon" + visible="false" + width="13" /> +</chiclet_im_group>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml new file mode 100644 index 0000000000..9283594a4c --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_im_p2p + font="SansSerif" + height="25" + name="im_p2p_chiclet" + show_speaker="false" + width="25"> + <chiclet_im_p2p.speaker + auto_update="true" + draw_border="false" + height="25" + left="25" + name="speaker" + visible="false" + width="20"/> + <chiclet_im_p2p.avatar_icon + follows="left|top|bottom" + height="22" + mouse_opaque="true" + name="avatar_icon" + width="22"/> + <chiclet_im_p2p.unread_notifications + height="25" + font="SansSerif" + font_halign="center" + left="25" + mouse_opaque="false" + name="unread" + text_color="white" + v_pad="5" + visible="false" + width="20"/> + <chiclet_im_p2p.new_message_icon + bottom="12" + height="13" + image_name="Unread_IM" + left="12" + name="new_message_icon" + visible="false" + width="13" /> +</chiclet_im_p2p>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml new file mode 100644 index 0000000000..5a22563758 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_offer + font="SansSerif" + height="25" + name="offer_chiclet" + width="25"> + <chiclet_offer.icon + default_icon="Generic_Object_Small" + follows="all" + height="22" + mouse_opaque="false" + name="chiclet_icon" + width="22"/> + <chiclet_offer.new_message_icon + bottom="12" + height="13" + image_name="Unread_IM" + left="12" + name="new_message_icon" + visible="false" + width="13" /> +</chiclet_offer>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml new file mode 100644 index 0000000000..f3207ddeae --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_panel + name="chiclet_panel" + chiclet_padding="3" + scrolling_offset="40" + scroll_button_hpad="5" + scroll_ratio="10" + min_width="180" + />
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml index e5af961a56..05a23b95f9 100644 --- a/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml @@ -1,10 +1,22 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<chiclet_script
- name="script_chiclet"
- font="SansSerif">
- <icon
- name="chiclet_icon"
- follows="all"
- mouse_opaque="false"
- image_name="Generic_Object_Small" />
-</expandable_text>
\ No newline at end of file +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_script + font="SansSerif" + height="25" + name="script_chiclet" + width="25"> + <chiclet_script.icon + follows="all" + height="22" + image_name="Generic_Object_Small" + mouse_opaque="false" + name="chiclet_icon" + width="22"/> + <chiclet_script.new_message_icon + bottom="12" + height="13" + image_name="Unread_IM" + left="12" + name="new_message_icon" + visible="false" + width="13" /> +</chiclet_script>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/group_icon.xml b/indra/newview/skins/default/xui/en/widgets/group_icon.xml new file mode 100644 index 0000000000..58d5e19fcc --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/group_icon.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<group_icon + default_icon_name="Generic_Group" + image_name="Generic_Group" + name="group_icon" /> diff --git a/indra/newview/skins/default/xui/en/widgets/location_input.xml b/indra/newview/skins/default/xui/en/widgets/location_input.xml index 7ac44b412d..1368c6826d 100644 --- a/indra/newview/skins/default/xui/en/widgets/location_input.xml +++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml @@ -95,12 +95,11 @@ follows="right|top" image_name="Parcel_ScriptsNo_Light" /> - <!-- NOTE: Placeholder icon, there is no dark grayscale version --> <damage_icon name="damage_icon" - width="22" - height="18" - top="21" + width="20" + height="16" + top="20" follows="right|top" image_name="Parcel_Damage_Light" /> diff --git a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml index 21b957d089..9d71ceca2f 100644 --- a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml +++ b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml @@ -1,9 +1,13 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <output_monitor + draw_border="true" + follows="top|left" image_mute="Parcel_VoiceNo_Light" image_off="VoicePTT_Off" image_on="VoicePTT_On" image_level_1="VoicePTT_Lvl1" image_level_2="VoicePTT_Lvl2" image_level_3="VoicePTT_Lvl3" + mouse_opaque="false" + name="output_monitor" /> diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml index 3368fa88ef..3f5a4b8379 100644 --- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml +++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml @@ -20,12 +20,12 @@ label_pad_left - padding to the left of tab button labels tab_top_image_selected="TabTop_Middle_Selected" tab_bottom_image_unselected="Toolbar_Middle_Off" tab_bottom_image_selected="Toolbar_Middle_Selected" - tab_left_image_unselected="TabTop_Middle_Off" - tab_left_image_selected="TabTop_Middle_Selected"/> + tab_left_image_unselected="SegmentedBtn_Left_Disabled" + tab_left_image_selected="SegmentedBtn_Left_Off"/> <last_tab tab_top_image_unselected="TabTop_Right_Off" tab_top_image_selected="TabTop_Right_Selected" tab_bottom_image_unselected="Toolbar_Right_Off" tab_bottom_image_selected="Toolbar_Right_Selected" - tab_left_image_unselected="TabTop_Middle_Off" - tab_left_image_selected="TabTop_Middle_Selected"/> + tab_left_image_unselected="SegmentedBtn_Left_Disabled" + tab_left_image_selected="SegmentedBtn_Left_Off"/> </tab_container> diff --git a/indra/newview/skins/default/xui/en/widgets/talk_button.xml b/indra/newview/skins/default/xui/en/widgets/talk_button.xml index 7781bdd066..68cf082c35 100644 --- a/indra/newview/skins/default/xui/en/widgets/talk_button.xml +++ b/indra/newview/skins/default/xui/en/widgets/talk_button.xml @@ -11,14 +11,14 @@ image_unselected="SegmentedBtn_Left_Off" image_pressed="SegmentedBtn_Left_Selected_Press" image_pressed_selected="SegmentedBtn_Left_Selected_Press" - name="left" + name="speak_btn" label="Speak" label_selected="Speak" tab_stop="false" /> <show_button follows="right" - name="right" + name="speak_flyout_btn" label="" left="0" top="0" diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index d2859db296..0db18525d7 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -354,6 +354,14 @@ class WindowsManifest(ViewerManifest): self.path("qtiffd4.dll") self.end_prefix() + # For WebKit/Qt plugin runtimes (codec/character encoding plugins) + if self.prefix(src="codecs", dst="codecs"): + self.path("qcncodecsd4.dll") + self.path("qjpcodecsd4.dll") + self.path("qkrcodecsd4.dll") + self.path("qtwcodecsd4.dll") + self.end_prefix() + self.end_prefix() else: if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'release'), @@ -377,6 +385,14 @@ class WindowsManifest(ViewerManifest): self.path("qtiff4.dll") self.end_prefix() + # For WebKit/Qt plugin runtimes (codec/character encoding plugins) + if self.prefix(src="codecs", dst="codecs"): + self.path("qcncodecs4.dll") + self.path("qjpcodecs4.dll") + self.path("qkrcodecs4.dll") + self.path("qtwcodecs4.dll") + self.end_prefix() + self.end_prefix() self.disable_manifest_check() diff --git a/indra/test_apps/llplugintest/CMakeLists.txt b/indra/test_apps/llplugintest/CMakeLists.txt index 89e2d8582d..b4043b0fd9 100644 --- a/indra/test_apps/llplugintest/CMakeLists.txt +++ b/indra/test_apps/llplugintest/CMakeLists.txt @@ -428,7 +428,23 @@ if(WINDOWS) ${plugintest_debug_files} ) set(plugin_test_targets ${plugin_test_targets} ${out_targets}) - + + # Debug config runtime files required for the plugin test mule (Qt codec plugins) + set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/codecs") + set(plugintest_debug_files + qcncodecsd4.dll + qjpcodecsd4.dll + qkrcodecsd4.dll + qtwcodecsd4.dll + ) + copy_if_different( + ${plugintest_debug_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/Debug/codecs" + out_targets + ${plugintest_debug_files} + ) + set(plugin_test_targets ${plugin_test_targets} ${out_targets}) + # Release & ReleaseDebInfo config runtime files required for the plugin test mule set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") set(plugintest_release_files @@ -486,6 +502,30 @@ if(WINDOWS) ${plugintest_release_files} ) set(plugin_test_targets ${plugin_test_targets} ${out_targets}) + + # Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt codec plugins) + set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/codecs") + set(plugintest_release_files + qcncodecs4.dll + qjpcodecs4.dll + qkrcodecs4.dll + qtwcodecs4.dll + ) + copy_if_different( + ${plugintest_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/Release/codecs" + out_targets + ${plugintest_release_files} + ) + set(plugin_test_targets ${plugin_test_targets} ${out_targets}) + + copy_if_different( + ${plugintest_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/codecs" + out_targets + ${plugintest_release_files} + ) + set(plugin_test_targets ${plugin_test_targets} ${out_targets}) add_custom_target(copy_plugintest_libs ALL DEPENDS diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index 018f691672..364088ab31 100644 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -235,6 +235,8 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential break; } + sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]); + // Here the login service at the current URI is redirecting us // to some other URI ("indeterminate" -- why not "redirect"?). // The response should contain another uri to try, with its @@ -276,7 +278,14 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential // Here we got through all the rewrittenURIs without succeeding. Tell // caller this didn't work out so well. Of course, the only failure data // we can reasonably show are from the last of the rewrittenURIs. - sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]); + + // *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an + // llsd with no "responses" node. To make the output from an incomplete login symmetrical + // to success, add a data/message and data/reason fields. + LLSD error_response; + error_response["reason"] = mAuthResponse["status"]; + error_response["message"] = mAuthResponse["error"]; + sendProgressEvent("offline", "fail.login", error_response); } void LLLogin::Impl::disconnect() diff --git a/install.xml b/install.xml index 0501ef9cfd..fdd7458384 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>1631831b63310d85ad272b4dca3c1fbf</string> + <string>5362a53488693f9bd7d9083758af25eb</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20091217.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20091218.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>3846354e2e20a98c0401317eb114ff5e</string> + <string>4dd305f2ce38b2e55a2014ad3a2de34d</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-qt4.6-20091215.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-qt4.6-20091218.tar.bz2</uri> </map> </map> </map> |