diff options
295 files changed, 17409 insertions, 15311 deletions
@@ -1,6 +1,10 @@ syntax: glob +# WinMerge temp files +*.bak +# Compiled python bytecode *.pyc +# Emacs temp files *~ .*.swp LICENSES diff --git a/indra/cmake/ExamplePlugin.cmake b/indra/cmake/ExamplePlugin.cmake new file mode 100644 index 0000000000..599787ad21 --- /dev/null +++ b/indra/cmake/ExamplePlugin.cmake @@ -0,0 +1,16 @@ +# -*- cmake -*- +include(Linking) +include(Prebuilt) + +if (STANDALONE) + set(EXAMPLEPLUGIN OFF CACHE BOOL + "EXAMPLEPLUGIN support for the llplugin/llmedia test apps.") +else (STANDALONE) + set(EXAMPLEPLUGIN ON CACHE BOOL + "EXAMPLEPLUGIN support for the llplugin/llmedia test apps.") +endif (STANDALONE) + +if (WINDOWS) +elseif (DARWIN) +elseif (LINUX) +endif (WINDOWS) diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp index 9e4957342c..6232c7588b 100644 --- a/indra/llcharacter/llvisualparam.cpp +++ b/indra/llcharacter/llvisualparam.cpp @@ -173,7 +173,8 @@ LLVisualParam::LLVisualParam() mTargetWeight( 0.f ), mIsAnimating( FALSE ), mID( -1 ), - mInfo( 0 ) + mInfo( 0 ), + mIsDummy(FALSE) { } @@ -251,6 +252,13 @@ void LLVisualParam::setWeight(F32 weight, BOOL set_by_user) //----------------------------------------------------------------------------- void LLVisualParam::setAnimationTarget(F32 target_value, BOOL set_by_user) { + // don't animate dummy parameters + if (mIsDummy) + { + setWeight(target_value, set_by_user); + return; + } + if (mInfo) { if (getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h index 0b516b9374..affc49debf 100644 --- a/indra/llcharacter/llvisualparam.h +++ b/indra/llcharacter/llvisualparam.h @@ -148,15 +148,19 @@ public: LLVisualParam* getNextParam() { return mNext; } void setNextParam( LLVisualParam *next ); - virtual void setAnimating(BOOL is_animating) { mIsAnimating = is_animating; } + virtual void setAnimating(BOOL is_animating) { mIsAnimating = is_animating && !mIsDummy; } BOOL getAnimating() const { return mIsAnimating; } + void setIsDummy(BOOL is_self) { mIsDummy = is_self; } + protected: F32 mCurWeight; // current weight F32 mLastWeight; // last weight LLVisualParam* mNext; // next param in a shared chain F32 mTargetWeight; // interpolation target BOOL mIsAnimating; // this value has been given an interpolation target + BOOL mIsDummy; // this is used to prevent dummy visual params from animating + S32 mID; // id for storing weight/morphtarget compares compactly LLVisualParamInfo *mInfo; diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index f2edd5c559..c027aa7bdd 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -671,9 +671,9 @@ std::string ll_convert_wide_to_string(const wchar_t* in) } #endif // LL_WINDOWS -long LLStringOps::sltOffset; -long LLStringOps::localTimeOffset; -bool LLStringOps::daylightSavings; +long LLStringOps::sPacificTimeOffset = 0; +long LLStringOps::sLocalTimeOffset = 0; +bool LLStringOps::sPacificDaylightTime = 0; std::map<std::string, std::string> LLStringOps::datetimeToCodes; S32 LLStringOps::collate(const llwchar* a, const llwchar* b) @@ -700,11 +700,11 @@ void LLStringOps::setupDatetimeInfo (bool daylight) tmpT = gmtime (&nowT); gmtT = mktime (tmpT); - localTimeOffset = (long) (gmtT - localT); + sLocalTimeOffset = (long) (gmtT - localT); - daylightSavings = daylight; - sltOffset = (daylightSavings? 7 : 8 ) * 60 * 60; + sPacificDaylightTime = daylight; + sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60; datetimeToCodes["wkday"] = "%a"; // Thu datetimeToCodes["weekday"] = "%A"; // Thursday @@ -957,36 +957,35 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, } else if (param != "utc") // slt { - secFromEpoch -= LLStringOps::getSltOffset(); + secFromEpoch -= LLStringOps::getPacificTimeOffset(); } // if never fell into those two ifs above, param must be utc if (secFromEpoch < 0) secFromEpoch = 0; - LLDate * datetime = new LLDate((F64)secFromEpoch); + LLDate datetime((F64)secFromEpoch); std::string code = LLStringOps::getDatetimeCode (token); // special case to handle timezone if (code == "%Z") { if (param == "utc") + { replacement = "GMT"; - else if (param == "slt") - replacement = "SLT"; - else if (param != "local") // *TODO Vadim: not local? then what? - replacement = LLStringOps::getDaylightSavings() ? "PDT" : "PST"; - - return true; - } - replacement = datetime->toHTTPDateString(code); - - if (code.empty()) - { - return false; - } - else - { + } + else if (param == "local") + { + replacement = ""; // user knows their own timezone + } + else + { + // "slt" = Second Life Time, which is deprecated. + // If not utc or user local time, fallback to Pacific time + replacement = LLStringOps::getPacificDaylightTime() ? "PDT" : "PST"; + } return true; } + replacement = datetime.toHTTPDateString(code); + return !code.empty(); } // LLStringUtil::format recogizes the following patterns. diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 0f2f05a0d8..edbb007f61 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -151,9 +151,9 @@ struct char_traits<U16> class LL_COMMON_API LLStringOps
{
private:
- static long sltOffset;
- static long localTimeOffset;
- static bool daylightSavings;
+ static long sPacificTimeOffset;
+ static long sLocalTimeOffset;
+ static bool sPacificDaylightTime;
static std::map<std::string, std::string> datetimeToCodes;
public:
@@ -184,10 +184,13 @@ public: static S32 collate(const char* a, const char* b) { return strcoll(a, b); }
static S32 collate(const llwchar* a, const llwchar* b);
- static void setupDatetimeInfo (bool daylight);
- static long getSltOffset (void) {return sltOffset;}
- static long getLocalTimeOffset (void) {return localTimeOffset;}
- static bool getDaylightSavings (void) {return daylightSavings;}
+ static void setupDatetimeInfo(bool pacific_daylight_time);
+ static long getPacificTimeOffset(void) { return sPacificTimeOffset;}
+ static long getLocalTimeOffset(void) { return sLocalTimeOffset;}
+ // Is the Pacific time zone (aka server time zone)
+ // currently in daylight savings time?
+ static bool getPacificDaylightTime(void) { return sPacificDaylightTime;}
+
static std::string getDatetimeCode (std::string key);
};
diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h index c18917b663..0cd9667644 100644 --- a/indra/llrender/lltexture.h +++ b/indra/llrender/lltexture.h @@ -61,6 +61,8 @@ public: // //interfaces to access LLViewerTexture // + virtual S8 getType() const = 0 ; + virtual void setKnownDrawSize(S32 width, S32 height) = 0 ; virtual bool bindDefaultImage(const S32 stage = 0) const = 0 ; virtual void forceImmediateUpdate() = 0 ; virtual void setActive() = 0 ; diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index fd369730d6..a7946cacf5 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -486,6 +486,11 @@ void LLButton::onMouseLeave(S32 x, S32 y, MASK mask) mNeedsHighlight = FALSE; } +void LLButton::setHighlight(bool b) +{ + mNeedsHighlight = b; +} + BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) { if (!childrenHandleHover(x, y, mask)) diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 7fc4997133..85580a98bf 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -176,6 +176,7 @@ public: BOOL getToggleState() const; void setToggleState(BOOL b); + void setHighlight(bool b); void setFlashing( BOOL b ); BOOL getFlashing() const { return mFlashing; } @@ -241,8 +242,8 @@ public: void setForcePressedState(BOOL b) { mForcePressedState = b; } protected: - const LLPointer<LLUIImage>& getImageUnselected() const { return mImageUnselected; } - const LLPointer<LLUIImage>& getImageSelected() const { return mImageSelected; } + LLPointer<LLUIImage> getImageUnselected() const { return mImageUnselected; } + LLPointer<LLUIImage> getImageSelected() const { return mImageSelected; } LLFrameTimer mMouseDownTimer; diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index 8eccd709ce..d9b98b1c28 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -49,9 +49,9 @@ #include "lluictrlfactory.h" const S32 LEADING_PAD = 5; -const S32 TITLE_PAD = 8; +const S32 TITLE_HPAD = 8; const S32 BORDER_PAD = 1; -const S32 LEFT_PAD = BORDER_PAD + TITLE_PAD + LEADING_PAD; +const S32 LEFT_PAD = BORDER_PAD + TITLE_HPAD + LEADING_PAD; const S32 RIGHT_PAD = BORDER_PAD + 32; // HACK: space for close btn and minimize btn S32 LLDragHandle::sSnapMargin = 5; @@ -240,19 +240,20 @@ void LLDragHandleLeft::draw() void LLDragHandleTop::reshapeTitleBox() { + static LLUICachedControl<S32> title_vpad("UIFloaterTitleVPad", 0); if( ! mTitleBox) { return; } const LLFontGL* font = LLFontGL::getFontSansSerif(); - S32 title_width = font->getWidth( mTitleBox->getText() ) + TITLE_PAD; + S32 title_width = font->getWidth( mTitleBox->getText() ) + TITLE_HPAD; if (getMaxTitleWidth() > 0) title_width = llmin(title_width, getMaxTitleWidth()); S32 title_height = llround(font->getLineHeight()); LLRect title_rect; title_rect.setLeftTopAndSize( LEFT_PAD, - getRect().getHeight() - BORDER_PAD, + getRect().getHeight() - title_vpad, getRect().getWidth() - LEFT_PAD - RIGHT_PAD, title_height); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 021e2e94ac..8c72b079ee 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -189,11 +189,14 @@ LLFloater::Params::Params() can_close("can_close", true), can_drag_on_left("can_drag_on_left", false), can_tear_off("can_tear_off", true), + save_dock_state("save_dock_state", false), save_rect("save_rect", false), save_visibility("save_visibility", false), + can_dock("can_dock", false), + header_height("header_height", 0), + legacy_header_height("legacy_header_height", 0), open_callback("open_callback"), - close_callback("close_callback"), - can_dock("can_dock", false) + close_callback("close_callback") { visible = false; } @@ -219,7 +222,7 @@ void LLFloater::initClass() static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(&typeid(LLFloater::Params), "floater"); LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) -: LLPanel(), +: LLPanel(), // intentionally do not pass params here, see initFromParams mDragHandle(NULL), mTitle(p.title), mShortTitle(p.short_title), @@ -233,6 +236,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) mResizable(p.can_resize), mMinWidth(p.min_width), mMinHeight(p.min_height), + mHeaderHeight(p.header_height), + mLegacyHeaderHeight(p.legacy_header_height), mMinimized(FALSE), mForeground(FALSE), mFirstLook(TRUE), @@ -263,11 +268,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) mButtonsEnabled[i] = FALSE; mButtons[i] = NULL; } - for (S32 i = 0; i < 4; i++) - { - mResizeBar[i] = NULL; - mResizeHandle[i] = NULL; - } + addDragHandle(); + addResizeCtrls(); initFromParams(p); @@ -280,10 +282,6 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) // Note: Floaters constructed from XML call init() twice! void LLFloater::initFloater() { - addDragHandle(); - - addResizeCtrls(); - // Close button. if (mCanClose) { @@ -323,9 +321,6 @@ void LLFloater::initFloater() void LLFloater::addDragHandle() { - static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0); - S32 close_box_size = mCanClose ? floater_close_box_size : 0; - if (!mDragHandle) { if (mDragOnLeft) @@ -346,6 +341,14 @@ void LLFloater::addDragHandle() } addChild(mDragHandle); } + layoutDragHandle(); +} + +void LLFloater::layoutDragHandle() +{ + static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0); + S32 close_box_size = mCanClose ? floater_close_box_size : 0; + LLRect rect; if (mDragOnLeft) { @@ -361,40 +364,17 @@ void LLFloater::addDragHandle() } void LLFloater::addResizeCtrls() -{ - for (S32 i = 0; i < 4; i++) - { - if (mResizeBar[i]) - { - removeChild(mResizeBar[i]); - delete mResizeBar[i]; - mResizeBar[i] = NULL; - } - if (mResizeHandle[i]) - { - removeChild(mResizeHandle[i]); - delete mResizeHandle[i]; - mResizeHandle[i] = NULL; - } - } - if( !mResizable ) - { - return; - } - +{ // Resize bars (sides) - const S32 RESIZE_BAR_THICKNESS = 3; LLResizeBar::Params p; p.name("resizebar_left"); p.resizing_view(this); - p.rect(LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0)); p.min_size(mMinWidth); p.side(LLResizeBar::LEFT); mResizeBar[LLResizeBar::LEFT] = LLUICtrlFactory::create<LLResizeBar>(p); addChild( mResizeBar[LLResizeBar::LEFT] ); p.name("resizebar_top"); - p.rect(LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS)); p.min_size(mMinHeight); p.side(LLResizeBar::TOP); @@ -402,15 +382,12 @@ void LLFloater::addResizeCtrls() addChild( mResizeBar[LLResizeBar::TOP] ); p.name("resizebar_right"); - p.rect(LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0)); p.min_size(mMinWidth); - p.side(LLResizeBar::RIGHT); - + p.side(LLResizeBar::RIGHT); mResizeBar[LLResizeBar::RIGHT] = LLUICtrlFactory::create<LLResizeBar>(p); addChild( mResizeBar[LLResizeBar::RIGHT] ); p.name("resizebar_bottom"); - p.rect(LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0)); p.min_size(mMinHeight); p.side(LLResizeBar::BOTTOM); mResizeBar[LLResizeBar::BOTTOM] = LLUICtrlFactory::create<LLResizeBar>(p); @@ -421,27 +398,69 @@ void LLFloater::addResizeCtrls() // handles must not be mouse-opaque, otherwise they block hover events // to other buttons like the close box. JC handle_p.mouse_opaque(false); - handle_p.rect(LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0)); handle_p.min_width(mMinWidth); handle_p.min_height(mMinHeight); handle_p.corner(LLResizeHandle::RIGHT_BOTTOM); mResizeHandle[0] = LLUICtrlFactory::create<LLResizeHandle>(handle_p); addChild(mResizeHandle[0]); - handle_p.rect(LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT)); handle_p.corner(LLResizeHandle::RIGHT_TOP); mResizeHandle[1] = LLUICtrlFactory::create<LLResizeHandle>(handle_p); addChild(mResizeHandle[1]); - handle_p.rect(LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 )); handle_p.corner(LLResizeHandle::LEFT_BOTTOM); mResizeHandle[2] = LLUICtrlFactory::create<LLResizeHandle>(handle_p); addChild(mResizeHandle[2]); - handle_p.rect(LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT )); handle_p.corner(LLResizeHandle::LEFT_TOP); mResizeHandle[3] = LLUICtrlFactory::create<LLResizeHandle>(handle_p); addChild(mResizeHandle[3]); + + layoutResizeCtrls(); +} + +void LLFloater::layoutResizeCtrls() +{ + LLRect rect; + + // Resize bars (sides) + const S32 RESIZE_BAR_THICKNESS = 3; + rect = LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0); + mResizeBar[LLResizeBar::LEFT]->setRect(rect); + + rect = LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS); + mResizeBar[LLResizeBar::TOP]->setRect(rect); + + rect = LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0); + mResizeBar[LLResizeBar::RIGHT]->setRect(rect); + + rect = LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0); + mResizeBar[LLResizeBar::BOTTOM]->setRect(rect); + + // Resize handles (corners) + rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0); + mResizeHandle[0]->setRect(rect); + + rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT); + mResizeHandle[1]->setRect(rect); + + rect = LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ); + mResizeHandle[2]->setRect(rect); + + rect = LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ); + mResizeHandle[3]->setRect(rect); +} + +void LLFloater::enableResizeCtrls(bool enable) +{ + for (S32 i = 0; i < 4; ++i) + { + mResizeBar[i]->setVisible(enable); + mResizeBar[i]->setEnabled(enable); + + mResizeHandle[i]->setVisible(enable); + mResizeHandle[i]->setEnabled(enable); + } } // virtual @@ -483,6 +502,7 @@ LLFloater::~LLFloater() storeRectControl(); setVisible(false); // We're not visible if we're destroyed storeVisibilityControl(); + storeDockStateControl(); } void LLFloater::storeRectControl() @@ -501,6 +521,15 @@ void LLFloater::storeVisibilityControl() } } +void LLFloater::storeDockStateControl() +{ + if( !sQuitting && mDocStateControl.size() > 1 ) + { + LLUI::sSettingGroups["floater"]->setBOOL( mDocStateControl, isDocked() ); + } +} + + void LLFloater::setVisible( BOOL visible ) { LLPanel::setVisible(visible); // calls handleVisibilityChange() @@ -759,6 +788,16 @@ void LLFloater::applyRectControl() } } +void LLFloater::applyDockState() +{ + if (mDocStateControl.size() > 1) + { + bool dockState = LLUI::sSettingGroups["floater"]->getBOOL(mDocStateControl); + setDocked(dockState); + } + +} + void LLFloater::applyTitle() { if (!mDragHandle) @@ -909,7 +948,8 @@ void LLFloater::handleReshape(const LLRect& new_rect, bool by_user) void LLFloater::setMinimized(BOOL minimize) { - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; static LLUICachedControl<S32> minimized_width ("UIMinimizedWidth", 0); if (minimize == mMinimized) return; @@ -1082,7 +1122,8 @@ void LLFloater::setFocus( BOOL b ) void LLFloater::setRect(const LLRect &rect) { LLPanel::setRect(rect); - addDragHandle(); // re-add drag handle, sized based on rect + layoutDragHandle(); + layoutResizeCtrls(); } // virtual @@ -1376,7 +1417,10 @@ void LLFloater::setDocked(bool docked, bool pop_on_undock) mButtonsEnabled[BUTTON_DOCK] = !mDocked; mButtonsEnabled[BUTTON_UNDOCK] = mDocked; updateButtons(); + + storeDockStateControl(); } + } // static @@ -1389,9 +1433,9 @@ void LLFloater::onClickMinimize(LLFloater* self) void LLFloater::onClickTearOff(LLFloater* self) { - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); if (!self) return; + S32 floater_header_size = self->mHeaderHeight; LLMultiFloater* host_floater = self->getHost(); if (host_floater) //Tear off { @@ -1548,26 +1592,42 @@ void LLFloater::draw() shadow_color % alpha, llround(shadow_offset)); - // No transparent windows in simple UI + LLUIImage* image = NULL; + LLColor4 color; if (isBackgroundOpaque()) { - gl_rect_2d( left, top, right, bottom, getBackgroundColor() % alpha ); + // NOTE: image may not be set + image = getBackgroundImage(); + color = getBackgroundColor(); } else { - gl_rect_2d( left, top, right, bottom, getTransparentColor() % alpha ); + image = getTransparentImage(); + color = getTransparentColor(); } - if(hasFocus() - && !getIsChrome() - && !getCurrentTitle().empty()) + if (image) + { + // We're using images for this floater's backgrounds + image->draw(getLocalRect(), UI_VERTEX_COLOR % alpha); + } + else { - static LLUIColor titlebar_focus_color = LLUIColorTable::instance().getColor("TitleBarFocusColor"); + // We're not using images, use old-school flat colors + gl_rect_2d( left, top, right, bottom, color % alpha ); + // draw highlight on title bar to indicate focus. RDW - const LLFontGL* font = LLFontGL::getFontSansSerif(); - LLRect r = getRect(); - gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1, - titlebar_focus_color % alpha, 0, TRUE); + if(hasFocus() + && !getIsChrome() + && !getCurrentTitle().empty()) + { + static LLUIColor titlebar_focus_color = LLUIColorTable::instance().getColor("TitleBarFocusColor"); + + const LLFontGL* font = LLFontGL::getFontSansSerif(); + LLRect r = getRect(); + gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1, + titlebar_focus_color % alpha, 0, TRUE); + } } } @@ -1617,18 +1677,6 @@ void LLFloater::draw() drawChild(focused_child); } - if( isBackgroundVisible() ) - { - // add in a border to improve spacialized visual aclarity ;) - // use lines instead of gl_rect_2d so we can round the edges as per james' recommendation - static LLUIColor focus_border_color = LLUIColorTable::instance().getColor("FloaterFocusBorderColor"); - static LLUIColor unfocus_border_color = LLUIColorTable::instance().getColor("FloaterUnfocusBorderColor"); - LLUI::setLineWidth(1.5f); - LLColor4 outlineColor = gFocusMgr.childHasKeyboardFocus(this) ? focus_border_color : unfocus_border_color; - gl_rect_2d_offset_local(0, getRect().getHeight() + 1, getRect().getWidth() + 1, 0, outlineColor % alpha, -LLPANEL_BORDER_WIDTH, FALSE); - LLUI::setLineWidth(1.f); - } - // update tearoff button for torn off floaters // when last host goes away if (mCanTearOff && !getHost()) @@ -1677,7 +1725,7 @@ void LLFloater::setCanTearOff(BOOL can_tear_off) void LLFloater::setCanResize(BOOL can_resize) { mResizable = can_resize; - addResizeCtrls(); + enableResizeCtrls(can_resize); } void LLFloater::setCanDrag(BOOL can_drag) @@ -2113,7 +2161,8 @@ void LLFloaterView::focusFrontFloater() void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) { - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; static LLUICachedControl<S32> minimized_width ("UIMinimizedWidth", 0); S32 col = 0; LLRect snap_rect_local = getLocalSnapRect(); @@ -2488,6 +2537,11 @@ void LLFloater::setInstanceName(const std::string& name) { mVisibilityControl = LLFloaterReg::declareVisibilityControl(mInstanceName); } + if(!mDocStateControl.empty()) + { + mDocStateControl = LLFloaterReg::declareDockStateControl(mInstanceName); + } + } } @@ -2528,6 +2582,9 @@ void LLFloater::setupParamsForExport(Params& p, LLView* parent) void LLFloater::initFromParams(const LLFloater::Params& p) { + // *NOTE: We have too many classes derived from LLFloater to retrofit them + // all to pass in params via constructors. So we use this method. + // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible LLPanel::initFromParams(p); @@ -2539,11 +2596,12 @@ void LLFloater::initFromParams(const LLFloater::Params& p) setCanMinimize(p.can_minimize); setCanClose(p.can_close); setCanDock(p.can_dock); + setCanResize(p.can_resize); + setResizeLimits(p.min_width, p.min_height); mDragOnLeft = p.can_drag_on_left; - mResizable = p.can_resize; - mMinWidth = p.min_width; - mMinHeight = p.min_height; + mHeaderHeight = p.header_height; + mLegacyHeaderHeight = p.legacy_header_height; mSingleInstance = p.single_instance; mAutoTile = p.auto_tile; @@ -2555,6 +2613,11 @@ void LLFloater::initFromParams(const LLFloater::Params& p) { mVisibilityControl = "t"; // flag to build mVisibilityControl name once mInstanceName is set } + + if(p.save_dock_state) + { + mDocStateControl = "t"; // flag to build mDocStateControl name once mInstanceName is set + } // open callback if (p.open_callback.isProvided()) @@ -2599,6 +2662,23 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o LLFloater::setFloaterHost(last_host); } + // HACK: When we changed the header height to 25 pixels in Viewer 2, rather + // than re-layout all the floaters we use this value in pixels to make the + // whole floater bigger and change the top-left coordinate for widgets. + // The goal is to eventually set mLegacyHeaderHeight to zero, which would + // make the top-left corner for widget layout the same as the top-left + // corner of the window's content area. James + S32 header_stretch = (mHeaderHeight - mLegacyHeaderHeight); + if (header_stretch > 0) + { + // Stretch the floater vertically, don't move widgets + LLRect rect = getRect(); + rect.mTop += header_stretch; + + // This will also update drag handle, title bar, close box, etc. + setRect(rect); + } + BOOL result; { LLFastTimer ft(POST_BUILD); @@ -2616,6 +2696,8 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o moveResizeHandlesToFront(); + applyDockState(); + return true; // *TODO: Error checking } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 2fdaecf59a..ef0d06a58e 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -124,7 +124,10 @@ public: can_tear_off, save_rect, save_visibility, + save_dock_state, can_dock; + Optional<S32> header_height, + legacy_header_height; // HACK see initFromXML() Optional<CommitCallbackParam> open_callback, close_callback; @@ -209,6 +212,7 @@ public: bool isDragOnLeft() const{ return mDragOnLeft; } S32 getMinWidth() const{ return mMinWidth; } S32 getMinHeight() const{ return mMinHeight; } + S32 getHeaderHeight() const { return mHeaderHeight; } virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); @@ -277,8 +281,10 @@ protected: void setRectControl(const std::string& rectname) { mRectControl = rectname; }; void applyRectControl(); + void applyDockState(); void storeRectControl(); void storeVisibilityControl(); + void storeDockStateControl(); void setKey(const LLSD& key); void setInstanceName(const std::string& name); @@ -302,7 +308,10 @@ private: void buildButtons(); BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index); void addResizeCtrls(); + void layoutResizeCtrls(); + void enableResizeCtrls(bool enable); void addDragHandle(); + void layoutDragHandle(); // repair layout public: // Called when floater is opened, passes mKey @@ -316,6 +325,7 @@ public: protected: std::string mRectControl; std::string mVisibilityControl; + std::string mDocStateControl; LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg LLDragHandle* mDragHandle; @@ -340,6 +350,8 @@ private: S32 mMinWidth; S32 mMinHeight; + S32 mHeaderHeight; // height in pixels of header for title, drag bar + S32 mLegacyHeaderHeight;// HACK see initFloaterXML() BOOL mMinimized; BOOL mForeground; diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 3c5a8a6921..8bb9e0d9ff 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -127,7 +127,7 @@ LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key) bool success = LLUICtrlFactory::getInstance()->buildFloater(res, xui_file, NULL); if (!success) { - llwarns << "Failed to buid floater type: '" << name << "'." << llendl; + llwarns << "Failed to build floater type: '" << name << "'." << llendl; return NULL; } @@ -364,6 +364,26 @@ std::string LLFloaterReg::declareVisibilityControl(const std::string& name) } //static +std::string LLFloaterReg::declareDockStateControl(const std::string& name) +{ + std::string controlname = getDockStateControlName(name); + LLUI::sSettingGroups["floater"]->declareBOOL(controlname, FALSE, + llformat("Window Docking state for %s", name.c_str()), + TRUE); + return controlname; + +} + +//static +std::string LLFloaterReg::getDockStateControlName(const std::string& name) +{ + std::string res = std::string("floater_dock_") + name; + LLStringUtil::replaceChar( res, ' ', '_' ); + return res; +} + + +//static void LLFloaterReg::registerControlVariables() { // Iterate through alll registered instance names and register rect and visibility control variables diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index 451bd1dbe3..634a235926 100644 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -121,6 +121,10 @@ public: static std::string declareRectControl(const std::string& name); static std::string getVisibilityControlName(const std::string& name); static std::string declareVisibilityControl(const std::string& name); + + static std::string declareDockStateControl(const std::string& name); + static std::string getDockStateControlName(const std::string& name); + static void registerControlVariables(); // Callback wrappers diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp index 66c2ba682f..b1bd2b89a9 100644 --- a/indra/llui/lliconctrl.cpp +++ b/indra/llui/lliconctrl.cpp @@ -57,7 +57,9 @@ LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p) : LLUICtrl(p), mColor(p.color()), mImagep(p.image), - mPriority(0) + mPriority(0), + mDrawWidth(0), + mDrawHeight(0) { if (mImagep.notNull()) { @@ -100,6 +102,8 @@ void LLIconCtrl::setValue(const LLSD& value ) { mImagep = LLUI::getUIImage(tvalue.asString(), mPriority); } + + setIconImageDrawSize(); } std::string LLIconCtrl::getImageName() const @@ -109,3 +113,15 @@ std::string LLIconCtrl::getImageName() const else return std::string(); } + +void LLIconCtrl::setIconImageDrawSize() +{ + if(mImagep.notNull() && mDrawWidth && mDrawHeight) + { + if(mImagep->getImage().notNull()) + { + mImagep->getImage()->setKnownDrawSize(mDrawWidth, mDrawHeight) ; + } + } +} + diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h index 90f1693060..66368f979b 100644 --- a/indra/llui/lliconctrl.h +++ b/indra/llui/lliconctrl.h @@ -60,6 +60,7 @@ public: protected: LLIconCtrl(const Params&); friend class LLUICtrlFactory; + public: virtual ~LLIconCtrl(); @@ -73,9 +74,16 @@ public: void setColor(const LLColor4& color) { mColor = color; } +private: + void setIconImageDrawSize() ; + protected: S32 mPriority; + //the output size of the icon image if set. + S32 mDrawWidth ; + S32 mDrawHeight ; + private: LLUIColor mColor; LLPointer<LLUIImage> mImagep; diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 8dbcd6e229..a657ed039a 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -85,6 +85,8 @@ void LLMenuButton::toggleMenu() void LLMenuButton::hideMenu() { + if(!mMenu) + return; mMenu->setVisible(FALSE); } diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index cf013efca0..91e7e46195 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -2894,8 +2894,8 @@ void hide_top_view( LLView* view ) } -// x and y are the desired location for the popup, NOT necessarily the -// mouse location +// x and y are the desired location for the popup, in the spawning_view's +// coordinate frame, NOT necessarily the mouse location // static void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) { @@ -3435,7 +3435,7 @@ void LLMenuHolderGL::setActivatedItem(LLMenuItemGL* item) LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) : LLFloater(LLSD()) { - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); + S32 floater_header_size = getHeaderHeight(); setName(menup->getName()); setTitle(menup->getLabel()); @@ -3479,7 +3479,6 @@ LLTearOffMenu::~LLTearOffMenu() void LLTearOffMenu::draw() { - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); mMenu->setBackgroundVisible(isBackgroundOpaque()); mMenu->needsArrange(); diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 48887ec352..09d9e407c7 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -505,7 +505,7 @@ public: void buildDrawLabels(); void createJumpKeys(); - // Show popup at a specific location. + // Show popup at a specific location, in the spawn_view's coordinate frame static void showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y); // Whether to drop shadow menu bar diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index e8ce1a8d97..78738c826d 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -54,7 +54,8 @@ LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params) void LLMultiFloater::buildTabContainer() { - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; LLTabContainer::Params p; p.name(std::string("Preview Tabs")); @@ -131,7 +132,8 @@ BOOL LLMultiFloater::closeAllFloaters() void LLMultiFloater::growToFit(S32 content_width, S32 content_height) { static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0); - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size; S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2); S32 new_height = llmax(getRect().getHeight(), content_height + floater_header_size + tabcntr_header_height); @@ -432,6 +434,7 @@ void LLMultiFloater::onTabSelected() void LLMultiFloater::setCanResize(BOOL can_resize) { LLFloater::setCanResize(can_resize); + if (!mTabContainer) return; if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM) { mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH); @@ -455,13 +458,16 @@ BOOL LLMultiFloater::postBuild() } mTabContainer = getChild<LLTabContainer>("Preview Tabs"); + + setCanResize(mResizable); return TRUE; } void LLMultiFloater::updateResizeLimits() { static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0); - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); + const LLFloater::Params& default_params = LLFloater::getDefaultParams(); + S32 floater_header_size = default_params.header_height; S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size; // initialize minimum size constraint to the original xml values. S32 new_min_width = mOrigMinWidth; diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 095200ddc3..07c0f3ce84 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -71,10 +71,12 @@ const LLPanel::Params& LLPanel::getDefaultParams() LLPanel::Params::Params() : has_border("border", false), border(""), - bg_opaque_color("bg_opaque_color"), - bg_alpha_color("bg_alpha_color"), background_visible("background_visible", false), background_opaque("background_opaque", false), + bg_opaque_color("bg_opaque_color"), + bg_alpha_color("bg_alpha_color"), + bg_opaque_image("bg_opaque_image"), + bg_alpha_image("bg_alpha_image"), min_width("min_width", 100), min_height("min_height", 100), strings("string"), @@ -92,10 +94,12 @@ LLPanel::Params::Params() LLPanel::LLPanel(const LLPanel::Params& p) : LLUICtrl(p), - mBgColorAlpha(p.bg_alpha_color()), - mBgColorOpaque(p.bg_opaque_color()), mBgVisible(p.background_visible), mBgOpaque(p.background_opaque), + mBgOpaqueColor(p.bg_opaque_color()), + mBgAlphaColor(p.bg_alpha_color()), + mBgOpaqueImage(p.bg_opaque_image()), + mBgAlphaImage(p.bg_alpha_image()), mDefaultBtn(NULL), mBorder(NULL), mLabel(p.label), @@ -103,9 +107,9 @@ LLPanel::LLPanel(const LLPanel::Params& p) mCommitCallbackRegistrar(false), mEnableCallbackRegistrar(false), mXMLFilename(p.filename) + // *NOTE: Be sure to also change LLPanel::initFromParams(). We have too + // many classes derived from LLPanel to retrofit them all to pass in params. { - setIsChrome(FALSE); - if (p.has_border) { addBorder(p.border); @@ -178,19 +182,31 @@ void LLPanel::draw() // draw background if( mBgVisible ) { - //RN: I don't see the point of this - S32 left = 0;//LLPANEL_BORDER_WIDTH; - S32 top = getRect().getHeight();// - LLPANEL_BORDER_WIDTH; - S32 right = getRect().getWidth();// - LLPANEL_BORDER_WIDTH; - S32 bottom = 0;//LLPANEL_BORDER_WIDTH; - + LLRect local_rect = getLocalRect(); if (mBgOpaque ) { - gl_rect_2d( left, top, right, bottom, mBgColorOpaque.get() % alpha); + // opaque, in-front look + if (mBgOpaqueImage.notNull()) + { + mBgOpaqueImage->draw( local_rect, UI_VERTEX_COLOR % alpha ); + } + else + { + // fallback to flat colors when there are no images + gl_rect_2d( local_rect, mBgOpaqueColor.get() % alpha); + } } else { - gl_rect_2d( left, top, right, bottom, mBgColorAlpha.get() % alpha); + // transparent, in-back look + if (mBgAlphaImage.notNull()) + { + mBgAlphaImage->draw( local_rect, UI_VERTEX_COLOR % alpha ); + } + else + { + gl_rect_2d( local_rect, mBgAlphaColor.get() % alpha ); + } } } @@ -443,7 +459,8 @@ void LLPanel::initFromParams(const LLPanel::Params& p) setBackgroundOpaque(p.background_opaque); setBackgroundColor(p.bg_opaque_color().get()); setTransparentColor(p.bg_alpha_color().get()); - + mBgOpaqueImage = p.bg_opaque_image(); + mBgAlphaImage = p.bg_alpha_image(); } static LLFastTimer::DeclareTimer FTM_PANEL_SETUP("Panel Setup"); diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index e8db68ffbb..c213809d68 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -48,6 +48,7 @@ const BOOL BORDER_YES = TRUE; const BOOL BORDER_NO = FALSE; class LLButton; +class LLUIImage; /* * General purpose concrete view base class. @@ -72,12 +73,15 @@ public: Optional<bool> has_border; Optional<LLViewBorder::Params> border; - Optional<LLUIColor> bg_opaque_color, - bg_alpha_color; - Optional<bool> background_visible, background_opaque; + Optional<LLUIColor> bg_opaque_color, + bg_alpha_color; + // opaque image is for "panel in foreground" look + Optional<LLUIImage*> bg_opaque_image, + bg_alpha_image; + Optional<S32> min_width, min_height; @@ -127,10 +131,12 @@ public: BOOL hasBorder() const { return mBorder != NULL; } void setBorderVisible( BOOL b ); - void setBackgroundColor( const LLColor4& color ) { mBgColorOpaque = color; } - const LLColor4& getBackgroundColor() const { return mBgColorOpaque; } - void setTransparentColor(const LLColor4& color) { mBgColorAlpha = color; } - const LLColor4& getTransparentColor() const { return mBgColorAlpha; } + void setBackgroundColor( const LLColor4& color ) { mBgOpaqueColor = color; } + const LLColor4& getBackgroundColor() const { return mBgOpaqueColor; } + void setTransparentColor(const LLColor4& color) { mBgAlphaColor = color; } + const LLColor4& getTransparentColor() const { return mBgAlphaColor; } + LLPointer<LLUIImage> getBackgroundImage() const { return mBgOpaqueImage; } + LLPointer<LLUIImage> getTransparentImage() const { return mBgAlphaImage; } void setBackgroundVisible( BOOL b ) { mBgVisible = b; } BOOL isBackgroundVisible() const { return mBgVisible; } void setBackgroundOpaque(BOOL b) { mBgOpaque = b; } @@ -248,10 +254,12 @@ protected: std::string mHelpTopic; // the name of this panel's help topic to display in the Help Viewer private: - LLUIColor mBgColorAlpha; - LLUIColor mBgColorOpaque; - BOOL mBgVisible; - BOOL mBgOpaque; + BOOL mBgVisible; // any background at all? + BOOL mBgOpaque; // use opaque color or image + LLUIColor mBgOpaqueColor; + LLUIColor mBgAlphaColor; + LLPointer<LLUIImage> mBgOpaqueImage; // "panel in front" look + LLPointer<LLUIImage> mBgAlphaImage; // "panel in back" look LLViewBorder* mBorder; LLButton* mDefaultBtn; LLUIString mLabel; diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp index f9f0307d17..86bd2f05ce 100644 --- a/indra/llui/llradiogroup.cpp +++ b/indra/llui/llradiogroup.cpp @@ -106,7 +106,7 @@ void LLRadioGroup::setIndexEnabled(S32 index, BOOL enabled) child->setEnabled(enabled); if (index == mSelectedIndex && enabled == FALSE) { - mSelectedIndex = -1; + setSelectedIndex(-1); } break; } diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp index 073e14386f..ba53f84877 100644 --- a/indra/llui/llscrolllistcolumn.cpp +++ b/indra/llui/llscrolllistcolumn.cpp @@ -47,6 +47,21 @@ const S32 MIN_COLUMN_WIDTH = 20; //--------------------------------------------------------------------------- // LLScrollColumnHeader //--------------------------------------------------------------------------- +LLScrollColumnHeader::Params::Params() +: column("column") +{ + name = "column_header"; + image_unselected.name("square_btn_32x128.tga"); + image_selected.name("square_btn_selected_32x128.tga"); + image_disabled.name("square_btn_32x128.tga"); + image_disabled_selected.name("square_btn_selected_32x128.tga"); + image_overlay.name("combobox_arrow.tga"); + image_overlay_alignment("right"); + font_halign = LLFontGL::LEFT; + tab_stop(false); + scale_image(true); +} + LLScrollColumnHeader::LLScrollColumnHeader(const LLScrollColumnHeader::Params& p) : LLButton(p), // use combobox params to steal images diff --git a/indra/llui/llscrolllistcolumn.h b/indra/llui/llscrolllistcolumn.h index 23318fd7c4..5aef6e8e94 100644 --- a/indra/llui/llscrolllistcolumn.h +++ b/indra/llui/llscrolllistcolumn.h @@ -50,20 +50,7 @@ public: { Mandatory<LLScrollListColumn*> column; - Params() - : column("column") - { - name = "column_header"; - image_unselected.name("square_btn_32x128.tga"); - image_selected.name("square_btn_selected_32x128.tga"); - image_disabled.name("square_btn_32x128.tga"); - image_disabled_selected.name("square_btn_selected_32x128.tga"); - image_overlay.name("combobox_arrow.tga"); - image_overlay_alignment("right"); - font_halign = LLFontGL::LEFT; - tab_stop(false); - scale_image(true); - } + Params(); }; LLScrollColumnHeader(const Params&); ~LLScrollColumnHeader(); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 2b1d677ffb..9a26f0b472 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -933,13 +933,16 @@ BOOL LLTextBase::handleToolTip(S32 x, S32 y, MASK mask) void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent) { - LLUICtrl::reshape( width, height, called_from_parent ); + if (width != getRect().getWidth() || height != getRect().getHeight()) + { + LLUICtrl::reshape( width, height, called_from_parent ); - // do this first after reshape, because other things depend on - // up-to-date mTextRect - updateRects(); - - needsReflow(); + // do this first after reshape, because other things depend on + // up-to-date mTextRect + updateRects(); + + needsReflow(); + } } void LLTextBase::draw() @@ -1193,11 +1196,10 @@ void LLTextBase::reflow(S32 start_index) //llassert_always(getLocalRectFromDocIndex(mScrollIndex).mBottom == first_char_rect.mBottom); } } - } - - // reset desired x cursor position - updateCursorXPos(); + // reset desired x cursor position + updateCursorXPos(); + } } LLRect LLTextBase::getContentsRect() @@ -2108,9 +2110,12 @@ LLRect LLTextBase::getVisibleDocumentRect() const } else { - // entire document rect when not scrolling + // entire document rect is visible when not scrolling + // but offset according to height of widget LLRect doc_rect = mDocumentView->getLocalRect(); - doc_rect.translate(-mDocumentView->getRect().mLeft, -mDocumentView->getRect().mBottom); + doc_rect.mLeft -= mDocumentView->getRect().mLeft; + // adjust for height of text above widget baseline + doc_rect.mBottom = llmin(0, doc_rect.getHeight() - mTextRect.getHeight()); return doc_rect; } } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 14fd786127..4cca522a23 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -154,6 +154,9 @@ public: LLRect getContentsRect(); LLRect getVisibleDocumentRect() const; + S32 getVPad() { return mVPad; } + S32 getHPad() { return mHPad; } + S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const; LLRect getLocalRectFromDocIndex(S32 pos) const; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index f0238dba49..3ce5a0320b 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -652,6 +652,13 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; + // set focus first, in case click callbacks want to change it + // RN: do we really need to have a tab stop? + if (hasTabStop()) + { + setFocus( TRUE ); + } + // Let scrollbar have first dibs handled = LLTextBase::handleMouseDown(x, y, mask); @@ -694,12 +701,6 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) handled = TRUE; } - if (hasTabStop()) - { - setFocus( TRUE ); - handled = TRUE; - } - // Delay cursor flashing resetCursorBlink(); @@ -708,29 +709,32 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = LLTextBase::handleRightMouseDown(x, y, mask); - if (!handled && hasTabStop()) + if (hasTabStop()) + { + setFocus(TRUE); + } + if (!LLTextBase::handleRightMouseDown(x, y, mask)) { - setFocus( TRUE ); showContextMenu(x, y); - handled = TRUE; } - return handled; + return TRUE; } BOOL LLTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - handled = LLTextBase::handleMouseDown(x, y, mask); + if (hasTabStop()) + { + setFocus(TRUE); + } - if (!handled) + if (!LLTextBase::handleMouseDown(x, y, mask)) { - setFocus( TRUE ); if( canPastePrimary() ) { setCursorAtLocalPos( x, y, true ); + // does not rely on focus being set pastePrimary(); } } diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index c8094f9c7c..23c87c7522 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -38,10 +38,11 @@ // Library includes #include "lltextbox.h" #include "lliconctrl.h" +#include "llbutton.h" #include "llmenugl.h" // hideMenus() #include "llui.h" // positionViewNearMouse() #include "llwindow.h" - +#include "lltrans.h" // // Constants // @@ -155,19 +156,23 @@ LLToolTip::Params::Params() visible_time_near("visible_time_near", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeNear" )), visible_time_far("visible_time_far", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeFar" )), sticky_rect("sticky_rect"), - image("image") + image("image"), + time_based_media("time_based_media", false), + web_based_media("web_based_media", false), + media_playing("media_playing", false) { - name = "tooltip"; - font = LLFontGL::getFontSansSerif(); - bg_opaque_color = LLUIColorTable::instance().getColor( "ToolTipBgColor" ); - background_visible = true; + chrome = true; } LLToolTip::LLToolTip(const LLToolTip::Params& p) : LLPanel(p), mMaxWidth(p.max_width), mHasClickCallback(p.click_callback.isProvided()), - mPadding(p.padding) + mPadding(p.padding), + mTextBox(NULL), + mInfoButton(NULL), + mPlayMediaButton(NULL), + mHomePageButton(NULL) { LLTextBox::Params params; params.initial_value = "tip_text"; @@ -186,25 +191,80 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) params.allow_html = false; // disallow hyperlinks in tooltips, as they want to spawn their own explanatory tooltips mTextBox = LLUICtrlFactory::create<LLTextBox> (params); addChild(mTextBox); - + + S32 TOOLTIP_ICON_SIZE = 0; + S32 TOOLTIP_PLAYBUTTON_SIZE = 0; if (p.image.isProvided()) { - LLIconCtrl::Params icon_params; - icon_params.name = "tooltip_icon"; + LLButton::Params icon_params; + icon_params.name = "tooltip_info"; LLRect icon_rect; LLUIImage* imagep = p.image; - const S32 TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16); + TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16); icon_rect.setOriginAndSize(mPadding, mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE); icon_params.rect = icon_rect; - icon_params.follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM; - icon_params.image = p.image; - icon_params.mouse_opaque = false; - addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_params)); - + //icon_params.follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM; + icon_params.image_unselected(imagep); + icon_params.image_selected(imagep); + icon_params.scale_image(true); + icon_params.flash_color(icon_params.highlight_color()); + mInfoButton = LLUICtrlFactory::create<LLButton>(icon_params); + if (p.click_callback.isProvided()) + { + mInfoButton->setCommitCallback(boost::bind(p.click_callback())); + } + addChild(mInfoButton); + // move text over to fit image in mTextBox->translate(TOOLTIP_ICON_SIZE + mPadding, 0); } - + + if (p.time_based_media) + { + LLButton::Params p_button; + p_button.name(std::string("play_media")); + TOOLTIP_PLAYBUTTON_SIZE = 16; + LLRect button_rect; + button_rect.setOriginAndSize((mPadding +TOOLTIP_ICON_SIZE+ mPadding ), mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE); + p_button.rect = button_rect; + p_button.image_selected.name("button_anim_pause.tga"); + p_button.image_unselected.name("button_anim_play.tga"); + p_button.scale_image(true); + + mPlayMediaButton = LLUICtrlFactory::create<LLButton>(p_button); + if(p.click_playmedia_callback.isProvided()) + { + mPlayMediaButton->setCommitCallback(boost::bind(p.click_playmedia_callback())); + } + mPlayMediaButton->setToggleState(p.media_playing); + addChild(mPlayMediaButton); + + // move text over to fit image in + mTextBox->translate(TOOLTIP_PLAYBUTTON_SIZE + mPadding, 0); + } + + if (p.web_based_media) + { + LLButton::Params p_w_button; + p_w_button.name(std::string("home_page")); + TOOLTIP_PLAYBUTTON_SIZE = 16; + LLRect button_rect; + button_rect.setOriginAndSize((mPadding +TOOLTIP_ICON_SIZE+ mPadding ), mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE); + p_w_button.rect = button_rect; + p_w_button.image_unselected.name("map_home.tga"); + p_w_button.scale_image(true); + + mHomePageButton = LLUICtrlFactory::create<LLButton>(p_w_button); + if(p.click_homepage_callback.isProvided()) + { + mHomePageButton->setCommitCallback(boost::bind(p.click_homepage_callback())); + } + addChild(mHomePageButton); + + // move text over to fit image in + mTextBox->translate(TOOLTIP_PLAYBUTTON_SIZE + mPadding, 0); + } + if (p.click_callback.isProvided()) { setMouseUpCallback(boost::bind(p.click_callback())); @@ -255,6 +315,10 @@ void LLToolTip::setVisible(BOOL visible) BOOL LLToolTip::handleHover(S32 x, S32 y, MASK mask) { + //mInfoButton->setFlashing(true); + if(mInfoButton) + mInfoButton->setHighlight(true); + LLPanel::handleHover(x, y, mask); if (mHasClickCallback) { @@ -263,6 +327,14 @@ BOOL LLToolTip::handleHover(S32 x, S32 y, MASK mask) return TRUE; } +void LLToolTip::onMouseLeave(S32 x, S32 y, MASK mask) +{ + //mInfoButton->setFlashing(true); + if(mInfoButton) + mInfoButton->setHighlight(false); + LLUICtrl::onMouseLeave(x, y, mask); +} + void LLToolTip::draw() { F32 alpha = 1.f; @@ -378,7 +450,10 @@ void LLToolTipMgr::show(const std::string& msg) void LLToolTipMgr::show(const LLToolTip::Params& params) { - if (!params.validateBlock()) + // fill in default tooltip params from tool_tip.xml + LLToolTip::Params params_with_defaults(params); + params_with_defaults.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLToolTip>()); + if (!params_with_defaults.validateBlock()) { llwarns << "Could not display tooltip!" << llendl; return; @@ -390,10 +465,12 @@ void LLToolTipMgr::show(const LLToolTip::Params& params) // are we ready to show the tooltip? if (!mToolTipsBlocked // we haven't hit a key, moved the mouse, etc. - && LLUI::getMouseIdleTime() > params.delay_time) // the mouse has been still long enough + && LLUI::getMouseIdleTime() > params_with_defaults.delay_time) // the mouse has been still long enough { - bool tooltip_changed = mLastToolTipParams.message() != params.message() - || mLastToolTipParams.pos() != params.pos(); + bool tooltip_changed = mLastToolTipParams.message() != params_with_defaults.message() + || mLastToolTipParams.pos() != params_with_defaults.pos() + || mLastToolTipParams.time_based_media() != params_with_defaults.time_based_media() + || mLastToolTipParams.web_based_media() != params_with_defaults.web_based_media(); bool tooltip_shown = mToolTip && mToolTip->getVisible() @@ -401,7 +478,7 @@ void LLToolTipMgr::show(const LLToolTip::Params& params) mNeedsToolTip = tooltip_changed || !tooltip_shown; // store description of tooltip for later creation - mNextToolTipParams = params; + mNextToolTipParams = params_with_defaults; } } diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h index 63e7249a12..30d251266c 100644 --- a/indra/llui/lltooltip.h +++ b/indra/llui/lltooltip.h @@ -78,9 +78,13 @@ public: visible_time_far; // time for which tooltip is visible while mouse moved away Optional<LLRect> sticky_rect; Optional<const LLFontGL*> font; - - Optional<click_callback_t> click_callback; Optional<LLUIImage*> image; + Optional<bool> time_based_media, + web_based_media, + media_playing; + Optional<click_callback_t> click_callback, + click_playmedia_callback, + click_homepage_callback; Optional<S32> max_width; Optional<S32> padding; Optional<bool> wrap; @@ -89,7 +93,7 @@ public: }; /*virtual*/ void draw(); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); - + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); /*virtual*/ void setValue(const LLSD& value); /*virtual*/ void setVisible(BOOL visible); @@ -101,6 +105,10 @@ public: private: class LLTextBox* mTextBox; + class LLButton* mInfoButton; + class LLButton* mPlayMediaButton; + class LLButton* mHomePageButton; + LLFrameTimer mFadeTimer; LLFrameTimer mVisibleTimer; S32 mMaxWidth; diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 48504a1e54..a82e6eb372 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1953,11 +1953,6 @@ namespace LLInitParam } } - if (mData.mValue == NULL) - { - mData.mValue = LLFontGL::getFontDefault(); - } - // default to current value return mData.mValue; } diff --git a/indra/llui/llui.h b/indra/llui/llui.h index efb1b0a36f..5ec07f1941 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -404,6 +404,20 @@ namespace LLInitParam LLUIColor getValueFromBlock() const; }; + // provide a better default for Optional<const LLFontGL*> than NULL + template <> + struct DefaultInitializer<const LLFontGL*> + { + // return reference to a single default instance of T + // built-in types will be initialized to zero, default constructor otherwise + static const LLFontGL* get() + { + static const LLFontGL* sDefaultFont = LLFontGL::getFontDefault(); + return sDefaultFont; + } + }; + + template<> class TypedParam<const LLFontGL*> : public BlockValue<const LLFontGL*> diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 0faff5eff6..08fc8fb784 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -42,6 +42,7 @@ static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl"); LLUICtrl::Params::Params() : tab_stop("tab_stop", true), + chrome("chrome", false), label("label"), initial_value("value"), init_callback("init_callback"), @@ -86,6 +87,7 @@ void LLUICtrl::initFromParams(const Params& p) { LLView::initFromParams(p); + setIsChrome(p.chrome); setControlName(p.control_name); if(p.enabled_controls.isProvided()) { @@ -582,7 +584,6 @@ void LLUICtrl::setIsChrome(BOOL is_chrome) // virtual BOOL LLUICtrl::getIsChrome() const { - LLView* parent_ctrl = getParent(); while(parent_ctrl) { diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 45fe47772b..dd22851100 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -126,7 +126,8 @@ public: struct Params : public LLInitParam::Block<Params, LLView::Params> { Optional<std::string> label; - Optional<bool> tab_stop; + Optional<bool> tab_stop, + chrome; Optional<LLSD> initial_value; Optional<CommitCallbackParam> init_callback, diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt index d35afd8cbd..cc03d9cb72 100644 --- a/indra/media_plugins/CMakeLists.txt +++ b/indra/media_plugins/CMakeLists.txt @@ -9,3 +9,5 @@ add_subdirectory(gstreamer010) if (WINDOWS OR DARWIN) add_subdirectory(quicktime) endif (WINDOWS OR DARWIN) + +add_subdirectory(example) diff --git a/indra/media_plugins/example/CMakeLists.txt b/indra/media_plugins/example/CMakeLists.txt new file mode 100644 index 0000000000..4d82f2747c --- /dev/null +++ b/indra/media_plugins/example/CMakeLists.txt @@ -0,0 +1,74 @@ +# -*- cmake -*- + +project(media_plugin_example) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLPlugin) +include(LLMath) +include(LLRender) +include(LLWindow) +include(Linking) +include(PluginAPI) +include(MediaPluginBase) +include(FindOpenGL) + +include(ExamplePlugin) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} +) + + +### media_plugin_example + +set(media_plugin_example_SOURCE_FILES + media_plugin_example.cpp + ) + +add_library(media_plugin_example + SHARED + ${media_plugin_example_SOURCE_FILES} +) + +target_link_libraries(media_plugin_example + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${EXAMPLE_PLUGIN_LIBRARIES} + ${PLUGIN_API_WINDOWS_LIBRARIES} +) + +add_dependencies(media_plugin_example + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} +) + +if (WINDOWS) + set_target_properties( + media_plugin_example + PROPERTIES + LINK_FLAGS "/MANIFEST:NO" + ) +endif (WINDOWS) + +if (DARWIN) + # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name + set_target_properties( + media_plugin_example + PROPERTIES + PREFIX "" + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path" + LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" + ) + +endif (DARWIN)
\ No newline at end of file diff --git a/indra/media_plugins/example/media_plugin_example.cpp b/indra/media_plugins/example/media_plugin_example.cpp new file mode 100644 index 0000000000..e873a0d034 --- /dev/null +++ b/indra/media_plugins/example/media_plugin_example.cpp @@ -0,0 +1,488 @@ +/** + * @file media_plugin_example.cpp + * @brief Example plugin for LLMedia API plugin system + * + * $LicenseInfo:firstyear=2008&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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 "linden_common.h" + +#include "llgl.h" +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#include <time.h> + +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginExample : + public MediaPluginBase +{ + public: + MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ); + ~MediaPluginExample(); + + /*virtual*/ void receiveMessage( const char* message_string ); + + private: + bool init(); + void update( int milliseconds ); + void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ); + bool mFirstTime; + + time_t mLastUpdateTime; + enum Constants { ENumObjects = 10 }; + unsigned char* mBackgroundPixels; + int mColorR[ ENumObjects ]; + int mColorG[ ENumObjects ]; + int mColorB[ ENumObjects ]; + int mXpos[ ENumObjects ]; + int mYpos[ ENumObjects ]; + int mXInc[ ENumObjects ]; + int mYInc[ ENumObjects ]; + int mBlockSize[ ENumObjects ]; + bool mMouseButtonDown; + bool mStopAction; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginExample::MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) : + MediaPluginBase( host_send_func, host_user_data ) +{ + mFirstTime = true; + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; + mMouseButtonDown = false; + mStopAction = false; + mLastUpdateTime = 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginExample::~MediaPluginExample() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginExample::receiveMessage( const char* message_string ) +{ + LLPluginMessage message_in; + + if ( message_in.parse( message_string ) >= 0 ) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + + if ( message_class == LLPLUGIN_MESSAGE_CLASS_BASE ) + { + if ( message_name == "init" ) + { + LLPluginMessage message( "base", "init_response" ); + LLSD versions = LLSD::emptyMap(); + versions[ LLPLUGIN_MESSAGE_CLASS_BASE ] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + message.setValueLLSD( "versions", versions ); + + std::string plugin_version = "Example media plugin, Example Version 1.0.0.0"; + message.setValue( "plugin_version", plugin_version ); + sendMessage( message ); + + // Plugin gets to decide the texture parameters to use. + message.setMessage( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" ); + message.setValueS32( "default_width", mWidth ); + message.setValueS32( "default_height", mHeight ); + message.setValueS32( "depth", mDepth ); + message.setValueU32( "internalformat", GL_RGBA ); + message.setValueU32( "format", GL_RGBA ); + message.setValueU32( "type", GL_UNSIGNED_BYTE ); + message.setValueBoolean( "coords_opengl", false ); + sendMessage( message ); + } + else + if ( message_name == "idle" ) + { + // no response is necessary here. + F64 time = message_in.getValueReal( "time" ); + + // Convert time to milliseconds for update() + update( time ); + } + else + if ( message_name == "cleanup" ) + { + // clean up here + } + else + if ( message_name == "shm_added" ) + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer( "address" ); + info.mSize = ( size_t )message_in.getValueS32( "size" ); + std::string name = message_in.getValue( "name" ); + + mSharedSegments.insert( SharedSegmentMap::value_type( name, info ) ); + + } + else + if ( message_name == "shm_remove" ) + { + std::string name = message_in.getValue( "name" ); + + SharedSegmentMap::iterator iter = mSharedSegments.find( name ); + if( iter != mSharedSegments.end() ) + { + if ( mPixels == iter->second.mAddress ) + { + // This is the currently active pixel buffer. + // Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + }; + mSharedSegments.erase( iter ); + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown shared memory region!" << std::endl; + }; + + // Send the response so it can be cleaned up. + LLPluginMessage message( "base", "shm_remove_response" ); + message.setValue( "name", name ); + sendMessage( message ); + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown base message: " << message_name << std::endl; + }; + } + else + if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA ) + { + if ( message_name == "size_change" ) + { + std::string name = message_in.getValue( "name" ); + S32 width = message_in.getValueS32( "width" ); + S32 height = message_in.getValueS32( "height" ); + S32 texture_width = message_in.getValueS32( "texture_width" ); + S32 texture_height = message_in.getValueS32( "texture_height" ); + + if ( ! name.empty() ) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find( name ); + if ( iter != mSharedSegments.end() ) + { + mPixels = ( unsigned char* )iter->second.mAddress; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + + init(); + }; + }; + + LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response" ); + message.setValue( "name", name ); + message.setValueS32( "width", width ); + message.setValueS32( "height", height ); + message.setValueS32( "texture_width", texture_width ); + message.setValueS32( "texture_height", texture_height ); + sendMessage( message ); + } + else + if ( message_name == "load_uri" ) + { + std::string uri = message_in.getValue( "uri" ); + if ( ! uri.empty() ) + { + }; + } + else + if ( message_name == "mouse_event" ) + { + std::string event = message_in.getValue( "event" ); + S32 button = message_in.getValueS32( "button" ); + + // left mouse button + if ( button == 0 ) + { + int mouse_x = message_in.getValueS32( "x" ); + int mouse_y = message_in.getValueS32( "y" ); + std::string modifiers = message_in.getValue( "modifiers" ); + + if ( event == "move" ) + { + if ( mMouseButtonDown ) + write_pixel( mouse_x, mouse_y, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80 ); + } + else + if ( event == "down" ) + { + mMouseButtonDown = true; + } + else + if ( event == "up" ) + { + mMouseButtonDown = false; + } + else + if ( event == "double_click" ) + { + }; + }; + } + else + if ( message_name == "key_event" ) + { + std::string event = message_in.getValue( "event" ); + S32 key = message_in.getValueS32( "key" ); + std::string modifiers = message_in.getValue( "modifiers" ); + + if ( event == "down" ) + { + if ( key == ' ') + { + mLastUpdateTime = 0; + update( 0 ); + }; + }; + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown media message: " << message_string << std::endl; + }; + } + else + if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ) + { + if ( message_name == "browse_reload" ) + { + mLastUpdateTime = 0; + mFirstTime = true; + mStopAction = false; + update( 0 ); + } + else + if ( message_name == "browse_stop" ) + { + for( int n = 0; n < ENumObjects; ++n ) + mXInc[ n ] = mYInc[ n ] = 0; + + mStopAction = true; + update( 0 ); + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown media_browser message: " << message_string << std::endl; + }; + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown message class: " << message_class << std::endl; + }; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginExample::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) +{ + // make sure we don't write outside the buffer + if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) ) + return; + + if ( mBackgroundPixels != NULL ) + { + unsigned char *pixel = mBackgroundPixels; + pixel += y * mWidth * mDepth; + pixel += ( x * mDepth ); + pixel[ 0 ] = b; + pixel[ 1 ] = g; + pixel[ 2 ] = r; + + setDirty( x, y, x + 1, y + 1 ); + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginExample::update( int milliseconds ) +{ + if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 ) + return; + + if ( mPixels == 0 ) + return; + + if ( mFirstTime ) + { + for( int n = 0; n < ENumObjects; ++n ) + { + mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 ); + mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 ); + + mColorR[ n ] = rand() % 0x60 + 0x60; + mColorG[ n ] = rand() % 0x60 + 0x60; + mColorB[ n ] = rand() % 0x60 + 0x60; + + mXInc[ n ] = 0; + while ( mXInc[ n ] == 0 ) + mXInc[ n ] = rand() % 7 - 3; + + mYInc[ n ] = 0; + while ( mYInc[ n ] == 0 ) + mYInc[ n ] = rand() % 9 - 4; + + mBlockSize[ n ] = rand() % 0x30 + 0x10; + }; + + delete [] mBackgroundPixels; + + mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ]; + + mFirstTime = false; + }; + + if ( mStopAction ) + return; + + if ( time( NULL ) > mLastUpdateTime + 3 ) + { + const int num_squares = rand() % 20 + 4; + int sqr1_r = rand() % 0x80 + 0x20; + int sqr1_g = rand() % 0x80 + 0x20; + int sqr1_b = rand() % 0x80 + 0x20; + int sqr2_r = rand() % 0x80 + 0x20; + int sqr2_g = rand() % 0x80 + 0x20; + int sqr2_b = rand() % 0x80 + 0x20; + + for ( int y1 = 0; y1 < num_squares; ++y1 ) + { + for ( int x1 = 0; x1 < num_squares; ++x1 ) + { + int px_start = mWidth * x1 / num_squares; + int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares; + int py_start = mHeight * y1 / num_squares; + int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares; + + for( int y2 = py_start; y2 < py_end; ++y2 ) + { + for( int x2 = px_start; x2 < px_end; ++x2 ) + { + int rowspan = mWidth * mDepth; + + if ( ( y1 % 2 ) ^ ( x1 % 2 ) ) + { + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b; + } + else + { + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b; + }; + }; + }; + }; + }; + + time( &mLastUpdateTime ); + }; + + memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth ); + + for( int n = 0; n < ENumObjects; ++n ) + { + if ( rand() % 50 == 0 ) + { + mXInc[ n ] = 0; + while ( mXInc[ n ] == 0 ) + mXInc[ n ] = rand() % 7 - 3; + + mYInc[ n ] = 0; + while ( mYInc[ n ] == 0 ) + mYInc[ n ] = rand() % 9 - 4; + }; + + if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] ) + mXInc[ n ] =- mXInc[ n ]; + + if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] ) + mYInc[ n ] =- mYInc[ n ]; + + mXpos[ n ] += mXInc[ n ]; + mYpos[ n ] += mYInc[ n ]; + + for( int y = 0; y < mBlockSize[ n ]; ++y ) + { + for( int x = 0; x < mBlockSize[ n ]; ++x ) + { + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ]; + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ]; + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ]; + }; + }; + }; + + setDirty( 0, 0, mWidth, mHeight ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +bool MediaPluginExample::init() +{ + LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); + message.setValue( "name", "Example Plugin" ); + sendMessage( message ); + + return true; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func, + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data ) +{ + MediaPluginExample* self = new MediaPluginExample( host_send_func, host_user_data ); + *plugin_send_func = MediaPluginExample::staticReceiveMessage; + *plugin_user_data = ( void* )self; + + return 0; +} diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp index 7c9e27a760..3ce8ff3deb 100644 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -207,14 +207,13 @@ private: // don't flip bitmap LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true ); - // Set the background color to black - LLQtWebKit::getInstance()-> // set background color to be black - mostly for initial login page LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, 0x00, 0x00, 0x00 ); - // go to the "home page" // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance. -// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" ); + // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially + // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date. + LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" ); // set flag so we don't do this again mBrowserInitialized = true; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 644ebfa3f4..e138b431c5 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1,1777 +1,1778 @@ -# -*- cmake -*-
-
-project(viewer)
-
-include(00-Common)
-include(Boost)
-include(BuildVersion)
-include(DBusGlib)
-include(DirectX)
-include(ELFIO)
-include(FMOD)
-include(OPENAL)
-include(FindOpenGL)
-include(LLAudio)
-include(LLCharacter)
-include(LLCommon)
-include(LLImage)
-include(LLImageJ2COJ)
-include(LLInventory)
-include(LLMath)
-include(LLMessage)
-include(LLPlugin)
-include(LLPrimitive)
-include(LLRender)
-include(LLUI)
-include(LLVFS)
-include(LLWindow)
-include(LLXML)
-include(LLXUIXML)
-include(LScript)
-include(Linking)
-include(NDOF)
-include(GooglePerfTools)
-include(TemplateCheck)
-include(UI)
-include(UnixInstall)
-include(LLKDU)
-include(ViewerMiscLibs)
-include(LLLogin)
-include(CMakeCopyIfDifferent)
-
-include_directories(
- ${DBUSGLIB_INCLUDE_DIRS}
- ${ELFIO_INCLUDE_DIR}
- ${LLAUDIO_INCLUDE_DIRS}
- ${LLCHARACTER_INCLUDE_DIRS}
- ${LLCOMMON_INCLUDE_DIRS}
- ${LLIMAGE_INCLUDE_DIRS}
- ${LLINVENTORY_INCLUDE_DIRS}
- ${LLMATH_INCLUDE_DIRS}
- ${LLMESSAGE_INCLUDE_DIRS}
- ${LLPLUGIN_INCLUDE_DIRS}
- ${LLPRIMITIVE_INCLUDE_DIRS}
- ${LLRENDER_INCLUDE_DIRS}
- ${LLUI_INCLUDE_DIRS}
- ${LLVFS_INCLUDE_DIRS}
- ${LLWINDOW_INCLUDE_DIRS}
- ${LLXML_INCLUDE_DIRS}
- ${LLXUIXML_INCLUDE_DIRS}
- ${LSCRIPT_INCLUDE_DIRS}
- ${LSCRIPT_INCLUDE_DIRS}/lscript_compile
- ${LLLOGIN_INCLUDE_DIRS}
- )
-
-set(viewer_SOURCE_FILES
- llaccordionctrl.cpp
- llaccordionctrltab.cpp
- llagent.cpp
- llagentaccess.cpp
- llagentdata.cpp
- llagentlanguage.cpp
- llagentlistener.cpp
- llagentpicksinfo.cpp
- llagentpilot.cpp
- llagentui.cpp
- llagentwearables.cpp
- llanimstatelabels.cpp
- llappearancemgr.cpp
- llappviewer.cpp
- llappviewerlistener.cpp
- llassetuploadqueue.cpp
- llassetuploadresponders.cpp
- llaudiosourcevo.cpp
- llavataractions.cpp
- llavatariconctrl.cpp
- llavatarlist.cpp
- llavatarlistitem.cpp
- llavatarpropertiesprocessor.cpp
- llbottomtray.cpp
- llbox.cpp
- llbreadcrumbview.cpp
- llcallbacklist.cpp
- llcallingcard.cpp
- llcapabilitylistener.cpp
- llcaphttpsender.cpp
- llchannelmanager.cpp
- llchatbar.cpp
- llchathistory.cpp
- llchatitemscontainerctrl.cpp
- llchatmsgbox.cpp
- llchiclet.cpp
- llclassifiedinfo.cpp
- llclassifiedstatsresponder.cpp
- llcloud.cpp
- llcolorswatch.cpp
- llcommandhandler.cpp
- llcommandlineparser.cpp
- llcompilequeue.cpp
- llconfirmationmanager.cpp
- llcurrencyuimanager.cpp
- llcylinder.cpp
- lldateutil.cpp
- lldebugmessagebox.cpp
- lldebugview.cpp
- lldelayedgestureerror.cpp
- lldirpicker.cpp
- lldndbutton.cpp
- lldrawable.cpp
- lldrawpool.cpp
- lldrawpoolalpha.cpp
- lldrawpoolavatar.cpp
- lldrawpoolbump.cpp
- lldrawpoolground.cpp
- lldrawpoolsimple.cpp
- lldrawpoolsky.cpp
- lldrawpoolterrain.cpp
- lldrawpooltree.cpp
- lldrawpoolwater.cpp
- lldrawpoolwlsky.cpp
- lldriverparam.cpp
- lldynamictexture.cpp
- llemote.cpp
- lleventinfo.cpp
- lleventnotifier.cpp
- lleventpoll.cpp
- llexpandabletextbox.cpp
- llface.cpp
- llfasttimerview.cpp
- llfavoritesbar.cpp
- llfeaturemanager.cpp
- llfilepicker.cpp
- llfirstuse.cpp
- llflexibleobject.cpp
- llfloaterabout.cpp
- llfloateractivespeakers.cpp
- llfloateranimpreview.cpp
- llfloaterauction.cpp
- llfloateravatarpicker.cpp
- llfloateravatartextures.cpp
- llfloaterbeacons.cpp
- llfloaterbuildoptions.cpp
- llfloaterbulkpermission.cpp
- llfloaterbump.cpp
- llfloaterbuy.cpp
- llfloaterbuycontents.cpp
- llfloaterbuycurrency.cpp
- llfloaterbuyland.cpp
- llfloatercall.cpp
- llfloatercamera.cpp
- llfloaterchat.cpp
- llfloaterchatterbox.cpp
- llfloatercolorpicker.cpp
- llfloatercustomize.cpp
- llfloaterdaycycle.cpp
- llfloaterenvsettings.cpp
- llfloaterfonttest.cpp
- llfloaterfriends.cpp
- llfloatergesture.cpp
- llfloatergodtools.cpp
- llfloatergroupinvite.cpp
- llfloatergroups.cpp
- llfloaterhandler.cpp
- llfloaterhardwaresettings.cpp
- llfloaterhelpbrowser.cpp
- llfloaterhud.cpp
- llfloaterimagepreview.cpp
- llfloaterinspect.cpp
- llfloaterinventory.cpp
- llfloaterjoystick.cpp
- llfloaterlagmeter.cpp
- llfloaterland.cpp
- llfloaterlandholdings.cpp
- llfloatermap.cpp
- llfloatermediabrowser.cpp
- llfloatermediasettings.cpp
- llfloatermemleak.cpp
- llfloaternamedesc.cpp
- llfloaternotificationsconsole.cpp
- llfloateropenobject.cpp
- llfloaterparcel.cpp
- llfloaterpay.cpp
- llfloaterperms.cpp
- llfloaterpostcard.cpp
- llfloaterpostprocess.cpp
- llfloaterpreference.cpp
- llfloaterproperties.cpp
- llfloaterregioninfo.cpp
- llfloaterreporter.cpp
- llfloaterscriptdebug.cpp
- llfloatersearch.cpp
- llfloatersellland.cpp
- llfloatersettingsdebug.cpp
- llfloatersnapshot.cpp
- llfloatertelehub.cpp
- llfloatertestinspectors.cpp
- llfloatertestlistview.cpp
- llfloatertools.cpp
- llfloatertopobjects.cpp
- llfloatertos.cpp
- llfloateruipreview.cpp
- llfloaterurldisplay.cpp
- llfloaterurlentry.cpp
- llfloatervoicedevicesettings.cpp
- llfloaterwater.cpp
- llfloaterwhitelistentry.cpp
- llfloaterwindlight.cpp
- llfloaterworldmap.cpp
- llfoldertype.cpp
- llfolderview.cpp
- llfolderviewitem.cpp
- llfollowcam.cpp
- llfriendcard.cpp
- llgesturemgr.cpp
- llglsandbox.cpp
- llgroupactions.cpp
- llgrouplist.cpp
- llgroupmgr.cpp
- llgroupnotify.cpp
- llhomelocationresponder.cpp
- llhudeffect.cpp
- llhudeffectbeam.cpp
- llhudeffectlookat.cpp
- llhudeffectpointat.cpp
- llhudeffecttrail.cpp
- llhudicon.cpp
- llhudmanager.cpp
- llhudobject.cpp
- llhudrender.cpp
- llhudtext.cpp
- llhudview.cpp
- llimcontrolpanel.cpp
- llimfloater.cpp
- llimhandler.cpp
- llimpanel.cpp
- llimview.cpp
- llinspect.cpp
- llinspectavatar.cpp
- llinspectgroup.cpp
- llinspectobject.cpp
- llinventorybridge.cpp
- llinventoryclipboard.cpp
- llinventoryfilter.cpp
- llinventoryfunctions.cpp
- llinventorymodel.cpp
- llinventorypanel.cpp
- llinventorysubtreepanel.cpp
- lljoystickbutton.cpp
- lllandmarkactions.cpp
- lllandmarklist.cpp
- lllistbrowser.cpp
- lllistview.cpp
- lllocaltextureobject.cpp
- lllocationhistory.cpp
- lllocationinputctrl.cpp
- lllogchat.cpp
- llloginhandler.cpp
- lllogininstance.cpp
- llmanip.cpp
- llmaniprotate.cpp
- llmanipscale.cpp
- llmaniptranslate.cpp
- llmapresponders.cpp
- llmediactrl.cpp
- llmediadataclient.cpp
- llmediaremotectrl.cpp
- llmemoryview.cpp
- llmenucommands.cpp
- llmetricperformancetester.cpp
- llmimetypes.cpp
- llmorphview.cpp
- llmoveview.cpp
- llmutelist.cpp
- llnamebox.cpp
- llnameeditor.cpp
- llnamelistctrl.cpp
- llnavigationbar.cpp
- llnearbychat.cpp
- llnearbychatbar.cpp
- llnearbychathandler.cpp
- llnetmap.cpp
- llnotificationalerthandler.cpp
- llnotificationgrouphandler.cpp
- llnotificationmanager.cpp
- llnotificationscripthandler.cpp
- llnotificationtiphandler.cpp
- llnotify.cpp
- lloutputmonitorctrl.cpp
- lloverlaybar.cpp
- llpanelappearance.cpp
- llpanelappearancetab.cpp
- llpanelavatar.cpp
- llpanelavatarrow.cpp
- llpanelavatartag.cpp
- llpanelblockedlist.cpp
- llpanelclassified.cpp
- llpanelcontents.cpp
- llpaneleditwearable.cpp
- llpanelevent.cpp
- llpanelface.cpp
- llpanelgroup.cpp
- llpanelgroupgeneral.cpp
- llpanelgroupinvite.cpp
- llpanelgrouplandmoney.cpp
- llpanelgroupnotices.cpp
- llpanelgrouproles.cpp
- llpanelimcontrolpanel.cpp
- llpanelland.cpp
- llpanellandaudio.cpp
- llpanellandmarks.cpp
- llpanellandmedia.cpp
- llpanellogin.cpp
- llpanellookinfo.cpp
- llpanellooks.cpp
- llpanelmaininventory.cpp
- llpanelmedia.cpp
- llpanelmediasettingsgeneral.cpp
- llpanelmediasettingspermissions.cpp
- llpanelmediasettingssecurity.cpp
- llpanelmeprofile.cpp
- llpanelobject.cpp
- llpanelobjectinventory.cpp
- llpanelpeople.cpp
- llpanelpeoplemenus.cpp
- llpanelpermissions.cpp
- llpanelpick.cpp
- llpanelpicks.cpp
- llpanelplace.cpp
- llpanelplaceinfo.cpp
- llpanelplaces.cpp
- llpanelplacestab.cpp
- llpanelprimmediacontrols.cpp
- llpanelprofile.cpp
- llpanelprofileview.cpp
- llpanelshower.cpp
- llpanelteleporthistory.cpp
- llpanelvolume.cpp
- llparcelselection.cpp
- llparticipantlist.cpp
- llpatchvertexarray.cpp
- llplacesinventorybridge.cpp
- llpolymesh.cpp
- llpolymorph.cpp
- llpreview.cpp
- llpreviewanim.cpp
- llpreviewgesture.cpp
- llpreviewnotecard.cpp
- llpreviewscript.cpp
- llpreviewsound.cpp
- llpreviewtexture.cpp
- llproductinforequest.cpp
- llprogressview.cpp
- llrecentpeople.cpp
- llregionposition.cpp
- llremoteparcelrequest.cpp
- llsavedsettingsglue.cpp
- llscreenchannel.cpp
- llscrollingpanelparam.cpp
- llsearchcombobox.cpp
- llsearchhistory.cpp
- llselectmgr.cpp
- llsidepanelinventory.cpp
- llsidepanelobjectinfo.cpp
- llsidetray.cpp
- llsidetraypanelcontainer.cpp
- llsky.cpp
- llslurl.cpp
- llspatialpartition.cpp
- llspeakers.cpp
- llsplitbutton.cpp
- llsprite.cpp
- llstartup.cpp
- llstatusbar.cpp
- llstylemap.cpp
- llsurface.cpp
- llsurfacepatch.cpp
- llsyswellitem.cpp
- llsyswellwindow.cpp
- llteleporthistory.cpp
- llteleporthistorystorage.cpp
- lltexglobalcolor.cpp
- lltexlayer.cpp
- lltexlayerparams.cpp
- lltextureatlas.cpp
- lltextureatlasmanager.cpp
- lltexturecache.cpp
- lltexturectrl.cpp
- lltexturefetch.cpp
- lltextureview.cpp
- lltoast.cpp
- lltoastalertpanel.cpp
- lltoastgroupnotifypanel.cpp
- lltoastimpanel.cpp
- lltoastnotifypanel.cpp
- lltoastpanel.cpp
- lltool.cpp
- lltoolbar.cpp
- lltoolbrush.cpp
- lltoolcomp.cpp
- lltooldraganddrop.cpp
- lltoolface.cpp
- lltoolfocus.cpp
- lltoolgrab.cpp
- lltoolgun.cpp
- lltoolindividual.cpp
- lltoolmgr.cpp
- lltoolmorph.cpp
- lltoolobjpicker.cpp
- lltoolpie.cpp
- lltoolpipette.cpp
- lltoolplacer.cpp
- lltoolselect.cpp
- lltoolselectland.cpp
- lltoolselectrect.cpp
- lltracker.cpp
- lltransientdockablefloater.cpp
- lltransientfloatermgr.cpp
- lluilistener.cpp
- lluploaddialog.cpp
- llurl.cpp
- llurldispatcher.cpp
- llurlhistory.cpp
- llurllineeditorctrl.cpp
- llurlsimstring.cpp
- llurlwhitelist.cpp
- llvectorperfoptions.cpp
- llviewchildren.cpp
- llviewerassetstorage.cpp
- llvieweraudio.cpp
- llviewercamera.cpp
- llviewercontrol.cpp
- llviewercontrollistener.cpp
- llviewerdisplay.cpp
- llviewerfloaterreg.cpp
- llviewergenericmessage.cpp
- llviewergesture.cpp
- llviewerhelp.cpp
- llviewerhelputil.cpp
- llviewerinventory.cpp
- llviewerjoint.cpp
- llviewerjointattachment.cpp
- llviewerjointmesh.cpp
- llviewerjointmesh_sse.cpp
- llviewerjointmesh_sse2.cpp
- llviewerjointmesh_vec.cpp
- llviewerjoystick.cpp
- llviewerkeyboard.cpp
- llviewerlayer.cpp
- llviewermedia.cpp
- llviewermedia_streamingaudio.cpp
- llviewermediafocus.cpp
- llviewermenu.cpp
- llviewermenufile.cpp
- llviewermessage.cpp
- llviewernetwork.cpp
- llviewerobject.cpp
- llviewerobjectlist.cpp
- llviewerparcelmedia.cpp
- llviewerparcelmediaautoplay.cpp
- llviewerparcelmgr.cpp
- llviewerparceloverlay.cpp
- llviewerpartsim.cpp
- llviewerpartsource.cpp
- llviewerregion.cpp
- llviewershadermgr.cpp
- llviewerstats.cpp
- llviewertexteditor.cpp
- llviewertexture.cpp
- llviewertextureanim.cpp
- llviewertexturelist.cpp
- llviewerthrottle.cpp
- llviewervisualparam.cpp
- llviewerwindow.cpp
- llviewerwindowlistener.cpp
- llvlcomposition.cpp
- llvlmanager.cpp
- llvoavatar.cpp
- llvoavatardefines.cpp
- llvoavatarself.cpp
- llvocache.cpp
- llvoclouds.cpp
- llvograss.cpp
- llvoground.cpp
- llvoicechannel.cpp
- llvoiceclient.cpp
- llvoicecontrolpanel.cpp
- llvoiceremotectrl.cpp
- llvoicevisualizer.cpp
- llvoinventorylistener.cpp
- llvopartgroup.cpp
- llvosky.cpp
- llvosurfacepatch.cpp
- llvotextbubble.cpp
- llvotree.cpp
- llvovolume.cpp
- llvowater.cpp
- llvowlsky.cpp
- llwatchdog.cpp
- llwaterparammanager.cpp
- llwaterparamset.cpp
- llwearable.cpp
- llwearabledictionary.cpp
- llwearablelist.cpp
- llweb.cpp
- llwind.cpp
- llwlanimator.cpp
- llwldaycycle.cpp
- llwlparammanager.cpp
- llwlparamset.cpp
- llworld.cpp
- llworldmap.cpp
- llworldmapview.cpp
- llxmlrpclistener.cpp
- llxmlrpctransaction.cpp
- noise.cpp
- pipeline.cpp
- )
-
-set(VIEWER_BINARY_NAME "secondlife-bin" CACHE STRING
- "The name of the viewer executable to create.")
-
-if (LINUX)
- # We can't set these flags for Darwin, because they get passed to
- # the PPC compiler. Ugh.
-
- set_source_files_properties(
- llviewerjointmesh_sse.cpp
- PROPERTIES COMPILE_FLAGS "-msse -mfpmath=sse"
- )
- set_source_files_properties(
- llviewerjointmesh_sse2.cpp
- PROPERTIES COMPILE_FLAGS "-msse2 -mfpmath=sse"
- )
-endif (LINUX)
-
-set(viewer_HEADER_FILES
- CMakeLists.txt
- ViewerInstall.cmake
- llaccordionctrl.h
- llaccordionctrltab.h
- llagent.h
- llagentaccess.h
- llagentdata.h
- llagentlanguage.h
- llagentlistener.h
- llagentpicksinfo.h
- llagentpilot.h
- llagentui.h
- llagentwearables.h
- llanimstatelabels.h
- llappearance.h
- llappearancemgr.h
- llappviewer.h
- llappviewerlistener.h
- llassetuploadqueue.h
- llassetuploadresponders.h
- llaudiosourcevo.h
- llavataractions.h
- llavatariconctrl.h
- llavatarlist.h
- llavatarlistitem.h
- llavatarpropertiesprocessor.h
- llbottomtray.h
- llbox.h
- llbreadcrumbview.h
- llcallbacklist.h
- llcallingcard.h
- llcapabilitylistener.h
- llcapabilityprovider.h
- llcaphttpsender.h
- llchannelmanager.h
- llchatbar.h
- llchathistory.h
- llchatitemscontainerctrl.h
- llchatmsgbox.h
- llchiclet.h
- llclassifiedinfo.h
- llclassifiedstatsresponder.h
- llcloud.h
- llcolorswatch.h
- llcommandhandler.h
- llcommandlineparser.h
- llcompilequeue.h
- llconfirmationmanager.h
- llcurrencyuimanager.h
- llcylinder.h
- lldateutil.h
- lldebugmessagebox.h
- lldebugview.h
- lldelayedgestureerror.h
- lldirpicker.h
- lldndbutton.h
- lldrawable.h
- lldrawpool.h
- lldrawpoolalpha.h
- lldrawpoolavatar.h
- lldrawpoolbump.h
- lldrawpoolclouds.h
- lldrawpoolground.h
- lldrawpoolsimple.h
- lldrawpoolsky.h
- lldrawpoolterrain.h
- lldrawpooltree.h
- lldrawpoolwater.h
- lldrawpoolwlsky.h
- lldriverparam.h
- lldynamictexture.h
- llemote.h
- lleventinfo.h
- lleventnotifier.h
- lleventpoll.h
- llexpandabletextbox.h
- llface.h
- llfasttimerview.h
- llfavoritesbar.h
- llfeaturemanager.h
- llfilepicker.h
- llfirstuse.h
- llflexibleobject.h
- llfloaterabout.h
- llfloateractivespeakers.h
- llfloateranimpreview.h
- llfloaterauction.h
- llfloateravatarpicker.h
- llfloateravatartextures.h
- llfloaterbeacons.h
- llfloaterbuildoptions.h
- llfloaterbulkpermission.h
- llfloaterbump.h
- llfloaterbuy.h
- llfloaterbuycontents.h
- llfloaterbuycurrency.h
- llfloaterbuyland.h
- llfloatercall.h
- llfloatercamera.h
- llfloaterchat.h
- llfloaterchatterbox.h
- llfloatercolorpicker.h
- llfloatercustomize.h
- llfloaterdaycycle.h
- llfloaterenvsettings.h
- llfloaterfonttest.h
- llfloaterfriends.h
- llfloatergesture.h
- llfloatergodtools.h
- llfloatergroupinvite.h
- llfloatergroups.h
- llfloaterhandler.h
- llfloaterhardwaresettings.h
- llfloaterhelpbrowser.h
- llfloaterhud.h
- llfloaterimagepreview.h
- llfloaterinspect.h
- llfloaterinventory.h
- llfloaterjoystick.h
- llfloaterlagmeter.h
- llfloaterland.h
- llfloaterlandholdings.h
- llfloatermap.h
- llfloatermediabrowser.h
- llfloatermediasettings.h
- llfloatermemleak.h
- llfloaternamedesc.h
- llfloaternotificationsconsole.h
- llfloateropenobject.h
- llfloaterparcel.h
- llfloaterpay.h
- llfloaterperms.h
- llfloaterpostcard.h
- llfloaterpostprocess.h
- llfloaterpreference.h
- llfloaterproperties.h
- llfloaterregioninfo.h
- llfloaterreporter.h
- llfloaterscriptdebug.h
- llfloatersearch.h
- llfloatersellland.h
- llfloatersettingsdebug.h
- llfloatersnapshot.h
- llfloatertelehub.h
- llfloatertestinspectors.h
- llfloatertestlistview.h
- llfloatertools.h
- llfloatertopobjects.h
- llfloatertos.h
- llfloateruipreview.h
- llfloaterurldisplay.h
- llfloaterurlentry.h
- llfloatervoicedevicesettings.h
- llfloaterwater.h
- llfloaterwhitelistentry.h
- llfloaterwindlight.h
- llfloaterworldmap.h
- llfoldertype.h
- llfolderview.h
- llfoldervieweventlistener.h
- llfolderviewitem.h
- llfollowcam.h
- llfriendcard.h
- llgesturemgr.h
- llgroupactions.h
- llgrouplist.h
- llgroupmgr.h
- llgroupnotify.h
- llhomelocationresponder.h
- llhudeffect.h
- llhudeffectbeam.h
- llhudeffectlookat.h
- llhudeffectpointat.h
- llhudeffecttrail.h
- llhudicon.h
- llhudmanager.h
- llhudobject.h
- llhudrender.h
- llhudtext.h
- llhudview.h
- llimcontrolpanel.h
- llimfloater.h
- llimpanel.h
- llimview.h
- llinspect.h
- llinspectavatar.h
- llinspectgroup.h
- llinspectobject.h
- llinventorybridge.h
- llinventoryclipboard.h
- llinventoryfilter.h
- llinventoryfunctions.h
- llinventorymodel.h
- llinventorypanel.h
- llinventorysubtreepanel.h
- lljoystickbutton.h
- lllandmarkactions.h
- lllandmarklist.h
- lllightconstants.h
- lllistbrowser.h
- lllistview.h
- lllocaltextureobject.h
- lllocationhistory.h
- lllocationinputctrl.h
- lllogchat.h
- llloginhandler.h
- lllogininstance.h
- llmanip.h
- llmaniprotate.h
- llmanipscale.h
- llmaniptranslate.h
- llmapresponders.h
- llmediactrl.h
- llmediadataclient.h
- llmediaremotectrl.h
- llmemoryview.h
- llmenucommands.h
- llmetricperformancetester.h
- llmimetypes.h
- llmorphview.h
- llmoveview.h
- llmutelist.h
- llnamebox.h
- llnameeditor.h
- llnamelistctrl.h
- llnavigationbar.h
- llnearbychat.h
- llnearbychatbar.h
- llnearbychathandler.h
- llnetmap.h
- llnotificationhandler.h
- llnotificationmanager.h
- llnotify.h
- lloutputmonitorctrl.h
- lloverlaybar.h
- llpanelappearance.h
- llpanelappearancetab.h
- llpanelavatar.h
- llpanelavatarrow.h
- llpanelavatartag.h
- llpanelblockedlist.h
- llpanelclassified.h
- llpanelcontents.h
- llpaneleditwearable.h
- llpanelevent.h
- llpanelface.h
- llpanelgroup.h
- llpanelgroupgeneral.h
- llpanelgroupinvite.h
- llpanelgrouplandmoney.h
- llpanelgroupnotices.h
- llpanelgrouproles.h
- llpanelimcontrolpanel.h
- llpanelinventory.h
- llpanelland.h
- llpanellandaudio.h
- llpanellandmarks.h
- llpanellandmedia.h
- llpanellogin.h
- llpanellookinfo.h
- llpanellooks.h
- llpanelmaininventory.h
- llpanelmedia.h
- llpanelmediasettingsgeneral.h
- llpanelmediasettingspermissions.h
- llpanelmediasettingssecurity.h
- llpanelmeprofile.h
- llpanelobject.h
- llpanelobjectinventory.h
- llpanelpeople.h
- llpanelpeoplemenus.h
- llpanelpermissions.h
- llpanelpick.h
- llpanelpicks.h
- llpanelplace.h
- llpanelplaceinfo.h
- llpanelplaces.h
- llpanelplacestab.h
- llpanelprimmediacontrols.h
- llpanelprofile.h
- llpanelprofileview.h
- llpanelshower.h
- llpanelteleporthistory.h
- llpanelvolume.h
- llparcelselection.h
- llparticipantlist.h
- llpatchvertexarray.h
- llplacesinventorybridge.h
- llpolymesh.h
- llpolymorph.h
- llpreview.h
- llpreviewanim.h
- llpreviewgesture.h
- llpreviewnotecard.h
- llpreviewscript.h
- llpreviewsound.h
- llpreviewtexture.h
- llproductinforequest.h
- llprogressview.h
- llrecentpeople.h
- llregionposition.h
- llremoteparcelrequest.h
- llresourcedata.h
- llrootview.h
- llsavedsettingsglue.h
- llscreenchannel.h
- llscrollingpanelparam.h
- llsearchcombobox.h
- llsearchhistory.h
- llselectmgr.h
- llsidepanelinventory.h
- llsidepanelobjectinfo.h
- llsidetray.h
- llsidetraypanelcontainer.h
- llsky.h
- llslurl.h
- llspatialpartition.h
- llspeakers.h
- llsplitbutton.h
- llsprite.h
- llstartup.h
- llstatusbar.h
- llstylemap.h
- llsurface.h
- llsurfacepatch.h
- llsyswellitem.h
- llsyswellwindow.h
- lltable.h
- llteleporthistory.h
- llteleporthistorystorage.h
- lltexglobalcolor.h
- lltexlayer.h
- lltexlayerparams.h
- lltextureatlas.h
- lltextureatlasmanager.h
- lltexturecache.h
- lltexturectrl.h
- lltexturefetch.h
- lltextureview.h
- lltoast.h
- lltoastalertpanel.h
- lltoastgroupnotifypanel.h
- lltoastimpanel.h
- lltoastnotifypanel.h
- lltoastpanel.h
- lltool.h
- lltoolbar.h
- lltoolbrush.h
- lltoolcomp.h
- lltooldraganddrop.h
- lltoolface.h
- lltoolfocus.h
- lltoolgrab.h
- lltoolgun.h
- lltoolindividual.h
- lltoolmgr.h
- lltoolmorph.h
- lltoolobjpicker.h
- lltoolpie.h
- lltoolpipette.h
- lltoolplacer.h
- lltoolselect.h
- lltoolselectland.h
- lltoolselectrect.h
- lltracker.h
- lltransientdockablefloater.h
- lltransientfloatermgr.h
- lluiconstants.h
- lluilistener.h
- lluploaddialog.h
- llurl.h
- llurldispatcher.h
- llurlhistory.h
- llurllineeditorctrl.h
- llurlsimstring.h
- llurlwhitelist.h
- llvectorperfoptions.h
- llviewchildren.h
- llviewerassetstorage.h
- llvieweraudio.h
- llviewerbuild.h
- llviewercamera.h
- llviewercontrol.h
- llviewercontrollistener.h
- llviewerdisplay.h
- llviewerfloaterreg.h
- llviewergenericmessage.h
- llviewergesture.h
- llviewerhelp.h
- llviewerinventory.h
- llviewerjoint.h
- llviewerjointattachment.h
- llviewerjointmesh.h
- llviewerjoystick.h
- llviewerkeyboard.h
- llviewerlayer.h
- llviewermedia.h
- llviewermediafocus.h
- llviewermediaobserver.h
- llviewermenu.h
- llviewermenufile.h
- llviewermessage.h
- llviewernetwork.h
- llviewerobject.h
- llviewerobjectlist.h
- llviewerparcelmedia.h
- llviewerparcelmediaautoplay.h
- llviewerparcelmgr.h
- llviewerparceloverlay.h
- llviewerpartsim.h
- llviewerpartsource.h
- llviewerprecompiledheaders.h
- llviewerregion.h
- llviewershadermgr.h
- llviewerstats.h
- llviewertexteditor.h
- llviewertexture.h
- llviewertextureanim.h
- llviewertexturelist.h
- llviewerthrottle.h
- llviewervisualparam.h
- llviewerwindow.h
- llviewerwindowlistener.h
- llvlcomposition.h
- llvlmanager.h
- llvoavatar.h
- llvoavatardefines.h
- llvoavatarself.h
- llvocache.h
- llvoclouds.h
- llvograss.h
- llvoground.h
- llvoicechannel.h
- llvoiceclient.h
- llvoicecontrolpanel.h
- llvoiceremotectrl.h
- llvoicevisualizer.h
- llvoinventorylistener.h
- llvopartgroup.h
- llvosky.h
- llvosurfacepatch.h
- llvotextbubble.h
- llvotree.h
- llvotreenew.h
- llvovolume.h
- llvowater.h
- llvowlsky.h
- llwatchdog.h
- llwaterparammanager.h
- llwaterparamset.h
- llwearable.h
- llwearabledictionary.h
- llwearablelist.h
- llweb.h
- llwind.h
- llwindebug.h
- llwlanimator.h
- llwldaycycle.h
- llwlparammanager.h
- llwlparamset.h
- llworld.h
- llworldmap.h
- llworldmapview.h
- llxmlrpclistener.h
- llxmlrpctransaction.h
- macmain.h
- noise.h
- pipeline.h
- randgauss.h
- VertexCache.h
- VorbisFramework.h
- )
-
-source_group("CMake Rules" FILES ViewerInstall.cmake)
-
-if (DARWIN)
- LIST(APPEND viewer_SOURCE_FILES llappviewermacosx.cpp)
-
- find_library(AGL_LIBRARY AGL)
- find_library(APPKIT_LIBRARY AppKit)
- find_library(COCOA_LIBRARY Cocoa)
- find_library(IOKIT_LIBRARY IOKit)
-
- set(viewer_LIBRARIES
- ${COCOA_LIBRARY}
- ${AGL_LIBRARY}
- ${IOKIT_LIBRARY}
- )
-
- # Add resource files to the project.
- set(viewer_RESOURCE_FILES
- secondlife.icns
- macview.r
- gpu_table.txt
- Info-SecondLife.plist
- SecondLife.nib/
- # CMake doesn't seem to support Xcode language variants well just yet
- English.lproj/InfoPlist.strings
- English.lproj/language.txt
- German.lproj/language.txt
- Japanese.lproj/language.txt
- Korean.lproj/language.txt
- )
- set_source_files_properties(
- ${viewer_RESOURCE_FILES}
- PROPERTIES
- HEADER_FILE_ONLY TRUE
- #MACOSX_PACKAGE_LOCATION Resources #don't do this! this tells cmake to copy the files.
- )
- SOURCE_GROUP("Resources" FILES ${viewer_RESOURCE_FILES})
- list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES})
-endif (DARWIN)
-
-if (LINUX)
- LIST(APPEND viewer_SOURCE_FILES llappviewerlinux.cpp)
- LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp)
- SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
-
- set(viewer_LIBRARIES
- Xinerama
- )
-endif (LINUX)
-
-if (WINDOWS)
- list(APPEND viewer_SOURCE_FILES
- llappviewerwin32.cpp
- llwindebug.cpp
- )
-
- list(APPEND viewer_HEADER_FILES
- llappviewerwin32.h
- llwindebug.h
- )
-
- # precompiled header configuration
- # llviewerprecompiledheaders.cpp generates
- # the .pch file.
- # All sources added to viewer_SOURCE_FILES
- # at this point use it.
- set_source_files_properties(llviewerprecompiledheaders.cpp
- PROPERTIES
- COMPILE_FLAGS "/Ycllviewerprecompiledheaders.h"
- )
- foreach( src_file ${viewer_SOURCE_FILES} )
- set_source_files_properties(
- ${src_file}
- PROPERTIES
- COMPILE_FLAGS "/Yullviewerprecompiledheaders.h"
- )
- endforeach( src_file ${viewer_SOURCE_FILES} )
- list(APPEND viewer_SOURCE_FILES llviewerprecompiledheaders.cpp)
- # llstartup.cpp needs special symbols for audio libraries, so it resets
- # COMPILE_FLAGS below. Make sure it maintains precompiled header settings.
- set(LLSTARTUP_COMPILE_FLAGS
- "${LLSTARTUP_COMPILE_FLAGS} /Yullviewerprecompiledheaders.h")
-
- # Add resource files to the project.
- # viewerRes.rc is the only buildable file, but
- # the rest are all dependencies of it.
- set(viewer_RESOURCE_FILES
- res/arrow.cur
- res/arrowcop.cur
- res/arrowcopmulti.cur
- res/arrowdrag.cur
- res/circleandline.cur
- res/icon1.ico
- res/llarrow.cur
- res/llarrowdrag.cur
- res/llarrowdragmulti.cur
- res/llarrowlocked.cur
- res/llgrablocked.cur
- res/llno.cur
- res/llnolocked.cur
- res/lltoolcamera.cur
- res/lltoolcreate.cur
- res/lltoolfocus.cur
- res/lltoolgrab.cur
- res/lltoolland.cur
- res/lltoolpan.cur
- res/lltoolpipette.cur
- res/lltoolrotate.cur
- res/lltoolscale.cur
- res/lltooltranslate.cur
- res/lltoolzoomin.cur
- res/lltoolzoomout.cur
- res/ll_icon.BMP
- res/ll_icon.ico
- res/resource.h
- res/toolpickobject.cur
- res/toolpickobject2.cur
- res/toolpickobject3.cur
- res/toolpipette.cur
- )
-
- set_source_files_properties(${viewer_RESOURCE_FILES}
- PROPERTIES HEADER_FILE_ONLY TRUE)
-
- set(viewer_RESOURCE_FILES
- res/viewerRes.rc
- ${viewer_RESOURCE_FILES}
- )
-
- SOURCE_GROUP("Resource Files" FILES ${viewer_RESOURCE_FILES})
-
- if (NOT STANDALONE)
- list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES})
- endif (NOT STANDALONE)
-
- find_library(DINPUT_LIBRARY dinput8 ${DIRECTX_LIBRARY_DIR})
- find_library(DXGUID_LIBRARY dxguid ${DIRECTX_LIBRARY_DIR})
- mark_as_advanced(
- DINPUT_LIBRARY
- DXGUID_LIBRARY
- )
-
- set(viewer_LIBRARIES
- ${WINDOWS_LIBRARIES}
- comdlg32
- ${DINPUT_LIBRARY}
- ${DXGUID_LIBRARY}
- kernel32
- odbc32
- odbccp32
- ole32
- oleaut32
- opengl32
- shell32
- Vfw32
- winspool
- )
-
- find_library(INTEL_MEMOPS_LIBRARY
- NAMES ll_intel_memops
- PATHS
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}
- debug ${ARCH_PREBUILT_DIRS_DEBUG}
- )
- mark_as_advanced(INTEL_MEMOPS_LIBRARY)
-
- if (INTEL_MEMOPS_LIBRARY)
- list(APPEND viewer_LIBRARIES ${INTEL_MEMOPS_LIBRARY})
- endif (INTEL_MEMOPS_LIBRARY)
-
- use_prebuilt_binary(dbghelp)
-endif (WINDOWS)
-
-# Add the xui files. This is handy for searching for xui elements
-# from within the IDE.
-set(viewer_XUI_FILES
- skins/default/colors.xml
- skins/default/textures/textures.xml
-
-
-
- )
-file(GLOB DEFAULT_XUI_FILE_GLOB_LIST
- ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en/*.xml)
-list(APPEND viewer_XUI_FILES ${DEFAULT_XUI_FILE_GLOB_LIST})
-
-file(GLOB DEFAULT_WIDGET_FILE_GLOB_LIST
- ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en/widgets/*.xml)
-list(APPEND viewer_XUI_FILES ${DEFAULT_WIDGET_FILE_GLOB_LIST})
-
-file(GLOB SILVER_XUI_FILE_GLOB_LIST
- ${CMAKE_CURRENT_SOURCE_DIR}/skins/silver/xui/en-us/*.xml)
-list(APPEND viewer_XUI_FILES ${SILVER_XUI_FILE_GLOB_LIST})
-
-# Cannot append empty lists in CMake, wait until we have files here.
-#file(GLOB SILVER_WIDGET_FILE_GLOB_LIST
-# ${CMAKE_CURRENT_SOURCE_DIR}/skins/silver/xui/en-us/widgets/*.xml)
-#list(APPEND viewer_XUI_FILES ${SILVER_WIDGET_FILE_GLOB_LIST})
-
-list(SORT viewer_XUI_FILES)
-
-source_group("XUI Files" FILES ${viewer_XUI_FILES})
-
-set_source_files_properties(${viewer_XUI_FILES}
- PROPERTIES HEADER_FILE_ONLY TRUE)
-
-list(APPEND viewer_SOURCE_FILES ${viewer_XUI_FILES})
-
-set(viewer_APPSETTINGS_FILES
- app_settings/anim.ini
- app_settings/cmd_line.xml
- app_settings/grass.xml
- app_settings/high_graphics.xml
- app_settings/keys.ini
- app_settings/keywords.ini
- app_settings/logcontrol.xml
- app_settings/low_graphics.xml
- app_settings/mid_graphics.xml
- app_settings/settings.xml
- app_settings/settings_crash_behavior.xml
- app_settings/settings_files.xml
- app_settings/settings_per_account.xml
- app_settings/std_bump.ini
- app_settings/trees.xml
- app_settings/ultra_graphics.xml
- app_settings/viewerart.xml
- ${CMAKE_SOURCE_DIR}/../etc/message.xml
- ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
- )
-
-use_prebuilt_binary(artwork-common)
-
-source_group("App Settings" FILES ${viewer_APPSETTINGS_FILES})
-
-set_source_files_properties(${viewer_APPSETTINGS_FILES}
- PROPERTIES HEADER_FILE_ONLY TRUE)
-
-list(APPEND viewer_SOURCE_FILES ${viewer_APPSETTINGS_FILES})
-
-set(viewer_CHARACTER_FILES
- character/attentions.xml
- character/attentionsN.xml
- character/avatar_lad.xml
- character/avatar_skeleton.xml
- character/genepool.xml
- )
-
-source_group("Character File" FILES ${viewer_CHARACTER_FILES})
-
-set_source_files_properties(${viewer_CHARACTER_FILES}
- PROPERTIES HEADER_FILE_ONLY TRUE)
-if (NOT STANDALONE)
- list(APPEND viewer_SOURCE_FILES ${viewer_CHARACTER_FILES})
-endif (NOT STANDALONE)
-
-if (WINDOWS)
- file(GLOB viewer_INSTALLER_FILES installers/windows/*.nsi)
-
- source_group("Installer Files" FILES ${viewer_INSTALLER_FILES})
-
- set_source_files_properties(${viewer_INSTALLER_FILES}
- PROPERTIES HEADER_FILE_ONLY TRUE)
-
- list(APPEND viewer_SOURCE_FILES ${viewer_INSTALLER_FILES})
-endif (WINDOWS)
-
-if (OPENAL)
- set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL")
-endif (OPENAL)
-
-if (FMOD)
- set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMOD")
-
- if (DARWIN)
- set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp)
- add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES})
- set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY})
- set_target_properties(
- fmodwrapper
- PROPERTIES
- BUILD_WITH_INSTALL_RPATH 1
- INSTALL_NAME_DIR "@executable_path/../Resources"
- LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp"
- )
- set(FMODWRAPPER_LIBRARY fmodwrapper)
- target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES})
- else (DARWIN)
- # fmodwrapper unnecessary on linux or windows
- set(FMODWRAPPER_LIBRARY ${FMOD_LIBRARY})
- endif (DARWIN)
-endif (FMOD)
-
-set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
-
-list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES})
-
-set_source_files_properties(${viewer_HEADER_FILES}
- PROPERTIES HEADER_FILE_ONLY TRUE)
-
-add_executable(${VIEWER_BINARY_NAME}
- WIN32
- MACOSX_BUNDLE
- ${viewer_SOURCE_FILES}
- )
-check_message_template(${VIEWER_BINARY_NAME})
-
-if (LLKDU_LIBRARY)
- add_dependencies(${VIEWER_BINARY_NAME} ${LLKDU_LIBRARY})
-endif (LLKDU_LIBRARY)
-
-# add package files
-file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST
- ${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py)
-list(APPEND EVENT_HOST_SCRIPTS ${EVENT_HOST_SCRIPT_GLOB_LIST})
-
-set(PACKAGE OFF CACHE BOOL
- "Add a package target that builds an installer package.")
-
-if (WINDOWS)
- if(MSVC71)
- set(release_flags "/MAP:Release/${VIEWER_BINARY_NAME}.map /MAPINFO:LINES")
- else(MSVC71)
- set(release_flags "/MAP:Release/${VIEWER_BINARY_NAME}.map")
- endif(MSVC71)
-
- set_target_properties(${VIEWER_BINARY_NAME}
- PROPERTIES
- # *TODO -reenable this once we get server usage sorted out
- #LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:\"__tcmalloc\""
- LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS"
- LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO"
- LINK_FLAGS_RELEASE ${release_flags}
- )
-
- # sets the 'working directory' for debugging from visual studio.
- if (NOT UNATTENDED)
- add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} PRE_BUILD
- COMMAND ${CMAKE_SOURCE_DIR}/tools/vstool/vstool.exe
- ARGS
- --solution
- ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.sln
- --workingdir
- ${VIEWER_BINARY_NAME}
- ${CMAKE_CURRENT_SOURCE_DIR}
- COMMENT "Setting the ${VIEWER_BINARY_NAME} working directory for debugging."
- )
- endif (NOT UNATTENDED)
-
- add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} PRE_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS
- -E
- copy_if_different
- ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/messages/message_template.msg
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings/message_template.msg
- COMMENT "Copying message_template.msg to the runtime folder."
- )
-
- add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} PRE_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS
- -E
- copy_if_different
- ${CMAKE_CURRENT_SOURCE_DIR}/../../etc/message.xml
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings/message.xml
- COMMENT "Copying message.xml to the runtime folder."
- )
-
- if(WINDOWS)
- # Copy Win Libs...
- # This happens at build time, not config time. We can't glob files in this cmake.
- # *FIX:Mani Write a sub script to glob the files...
- # *FIX:Mani Use actually dependencies rather than bulk copy.
- add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} PRE_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS
- -E
- copy_directory
- ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
- COMMENT "Copying staged dlls."
- )
-
- add_dependencies(${VIEWER_BINARY_NAME} stage_third_party_libs llcommon)
- if(LLKDU_LIBRARY)
- # kdu may not exist!
- add_dependencies(${VIEWER_BINARY_NAME} llkdu)
- endif(LLKDU_LIBRARY)
- endif(WINDOWS)
-
- if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
- add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
- endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
-
- add_custom_command(
- OUTPUT ${CMAKE_CFG_INTDIR}/touched.bat
- COMMAND ${PYTHON_EXECUTABLE}
- ARGS
- ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- --configuration=${CMAKE_CFG_INTDIR}
- --channel=${VIEWER_CHANNEL}
- --login_channel=${VIEWER_LOGIN_CHANNEL}
- --grid=${GRID}
- --source=${CMAKE_CURRENT_SOURCE_DIR}
- --artwork=${ARTWORK_DIR}
- --build=${CMAKE_CURRENT_BINARY_DIR}
- --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
- --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/touched.bat
- DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- )
-
- add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit)
-
- if (PACKAGE)
- add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2
- COMMAND ${PYTHON_EXECUTABLE}
- ARGS
- ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py
- ${CMAKE_CURRENT_SOURCE_DIR}/..
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_CFG_INTDIR}
-
- DEPENDS
- lleventhost
- ${EVENT_HOST_SCRIPTS}
- ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py)
-
- add_custom_target(package ALL
- DEPENDS
- ${CMAKE_CFG_INTDIR}/touched.bat)
- # temporarily disable packaging of event_host until hg subrepos get
- # sorted out on the parabuild cluster...
- #${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2)
- add_dependencies(package windows-updater windows-crash-logger)
-
-
- endif (PACKAGE)
-endif (WINDOWS)
-
-target_link_libraries(${VIEWER_BINARY_NAME}
- ${LLAUDIO_LIBRARIES}
- ${LLCHARACTER_LIBRARIES}
- ${LLIMAGE_LIBRARIES}
- ${LLIMAGEJ2COJ_LIBRARIES}
- ${LLINVENTORY_LIBRARIES}
- ${LLMESSAGE_LIBRARIES}
- ${LLPLUGIN_LIBRARIES}
- ${LLPRIMITIVE_LIBRARIES}
- ${LLRENDER_LIBRARIES}
- ${FREETYPE_LIBRARIES}
- ${LLUI_LIBRARIES}
- ${LLVFS_LIBRARIES}
- ${LLWINDOW_LIBRARIES}
- ${LLXML_LIBRARIES}
- ${LLXUIXML_LIBRARIES}
- ${LSCRIPT_LIBRARIES}
- ${LLMATH_LIBRARIES}
- ${LLCOMMON_LIBRARIES}
- ${NDOF_LIBRARY}
- ${viewer_LIBRARIES}
- ${BOOST_PROGRAM_OPTIONS_LIBRARY}
- ${BOOST_REGEX_LIBRARY}
- ${DBUSGLIB_LIBRARIES}
- ${OPENGL_LIBRARIES}
- ${FMODWRAPPER_LIBRARY}
- ${OPENGL_LIBRARIES}
- ${SDL_LIBRARY}
- ${SMARTHEAP_LIBRARY}
- ${UI_LIBRARIES}
- ${WINDOWS_LIBRARIES}
- ${XMLRPCEPI_LIBRARIES}
- ${ELFIO_LIBRARIES}
- ${LLLOGIN_LIBRARIES}
- ${GOOGLE_PERFTOOLS_LIBRARIES}
- )
-
-build_version(viewer)
-
-set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH
- "Path to artwork files.")
-
-
-if (LINUX)
- add_custom_command(
- OUTPUT secondlife-stripped
- COMMAND strip
- ARGS --strip-debug -o secondlife-stripped ${VIEWER_BINARY_NAME}
- DEPENDS ${VIEWER_BINARY_NAME}
- )
-
- set(product SecondLife-${ARCH}-${viewer_VERSION})
-
- add_custom_command(
- OUTPUT ${product}.tar.bz2
- COMMAND ${PYTHON_EXECUTABLE}
- ARGS
- ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- --grid=${GRID}
- --channel=${VIEWER_CHANNEL}
- --login_channel=${VIEWER_LOGIN_CHANNEL}
- --installer_name=${product}
- --arch=${ARCH}
- --source=${CMAKE_CURRENT_SOURCE_DIR}
- --artwork=${ARTWORK_DIR}
- --build=${CMAKE_CURRENT_BINARY_DIR}
- --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged
- --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched
- DEPENDS secondlife-stripped ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- )
-
- add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer010 media_plugin_webkit)
-
- if (NOT INSTALL)
- add_custom_target(package ALL DEPENDS ${product}.tar.bz2)
- add_dependencies(package linux-crash-logger-strip-target)
- add_dependencies(package linux-updater-strip-target)
- endif (NOT INSTALL)
-endif (LINUX)
-
-if (DARWIN)
- set(product "Second Life")
- set_target_properties(
- ${VIEWER_BINARY_NAME}
- PROPERTIES
- OUTPUT_NAME "${product}"
- MACOSX_BUNDLE_INFO_STRING "info string - localize me"
- MACOSX_BUNDLE_ICON_FILE "secondlife.icns"
- MACOSX_BUNDLE_GUI_IDENTIFIER "Second Life"
- MACOSX_BUNDLE_LONG_VERSION_STRING "ververver"
- MACOSX_BUNDLE_BUNDLE_NAME "Second Life"
- MACOSX_BUNDLE_SHORT_VERSION_STRING "asdf"
- MACOSX_BUNDLE_BUNDLE_VERSION "asdf"
- MACOSX_BUNDLE_COPYRIGHT "copyright linden lab 2007 - localize me and run me through a legal wringer"
- )
-
- add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} POST_BUILD
- COMMAND ${PYTHON_EXECUTABLE}
- ARGS
- ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- --grid=${GRID}
- --actions=copy
- --configuration=${CMAKE_CFG_INTDIR}
- --source=${CMAKE_CURRENT_SOURCE_DIR}
- --artwork=${ARTWORK_DIR}
- --build=${CMAKE_CURRENT_BINARY_DIR}
- --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app
- DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- )
-
- add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit)
-
- if (PACKAGE)
- add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME})
- add_dependencies(package mac-updater mac-crash-logger)
-
- add_custom_command(
- TARGET package POST_BUILD
- COMMAND ${PYTHON_EXECUTABLE}
- ARGS
- ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- --grid=${GRID}
- --configuration=${CMAKE_CFG_INTDIR}
- --channel=${VIEWER_CHANNEL}
- --login_channel=${VIEWER_LOGIN_CHANNEL}
- --source=${CMAKE_CURRENT_SOURCE_DIR}
- --artwork=${ARTWORK_DIR}
- --build=${CMAKE_CURRENT_BINARY_DIR}
- --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app
- --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched
- DEPENDS
- ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- )
-
-
- add_custom_command(
- TARGET package POST_BUILD
- COMMAND ${PYTHON_EXECUTABLE}
- ARGS
- ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- --grid=${GRID}
- --configuration=${CMAKE_CFG_INTDIR}
- --channel=${VIEWER_CHANNEL}
- --login_channel=${VIEWER_LOGIN_CHANNEL}
- --source=${CMAKE_CURRENT_SOURCE_DIR}
- --artwork=${ARTWORK_DIR}
- --build=${CMAKE_CURRENT_BINARY_DIR}
- --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app
- --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched
- DEPENDS
- ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- )
-
- endif (PACKAGE)
-endif (DARWIN)
-
-if (INSTALL)
- include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake)
-endif (INSTALL)
-
-# To add a viewer unit test, just add the test .cpp file below
-# This creates a separate test project per file listed.
-include(LLAddBuildTest)
-SET(viewer_TEST_SOURCE_FILES
- llagentaccess.cpp
- lldateutil.cpp
- llmediadataclient.cpp
- llviewerhelputil.cpp
- lllogininstance.cpp
- )
-set_source_files_properties(
- ${viewer_TEST_SOURCE_FILES}
- PROPERTIES
- LL_TEST_ADDITIONAL_SOURCE_FILES llviewerprecompiledheaders.cpp
- )
-LL_ADD_PROJECT_UNIT_TESTS(${VIEWER_BINARY_NAME} "${viewer_TEST_SOURCE_FILES}")
-
-#set(TEST_DEBUG on)
-set(test_sources llcapabilitylistener.cpp llviewerprecompiledheaders.cpp)
-set(test_libs
- ${LLMESSAGE_LIBRARIES}
- ${WINDOWS_LIBRARIES}
- ${LLVFS_LIBRARIES}
- ${LLMATH_LIBRARIES}
- ${LLCOMMON_LIBRARIES}
- ${GOOGLEMOCK_LIBRARIES}
- )
-
-LL_ADD_INTEGRATION_TEST(llcapabilitylistener
- "${test_sources}"
- "${test_libs}"
- ${PYTHON_EXECUTABLE}
- "${CMAKE_SOURCE_DIR}/llmessage/tests/test_llsdmessage_peer.py"
- )
-
-#ADD_VIEWER_BUILD_TEST(llmemoryview viewer)
-
-
-# Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py
-if (WINDOWS)
- add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} POST_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS
- -E
- make_directory
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin
- COMMENT "Creating llplugin dir."
- )
-
- get_target_property(BUILT_SLPLUGIN SLPlugin LOCATION)
- add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} POST_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS
- -E
- copy_if_different
- ${BUILT_SLPLUGIN}
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
- COMMENT "Copying SLPlugin executable to the runtime folder."
- )
-
- get_target_property(BUILT_WEBKIT_PLUGIN media_plugin_webkit LOCATION)
- add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} POST_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS
- -E
- copy_if_different
- ${BUILT_WEBKIT_PLUGIN}
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin
- COMMENT "Copying WebKit Plugin to the runtime folder."
- )
-
- get_target_property(BUILT_QUICKTIME_PLUGIN media_plugin_quicktime LOCATION)
- add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} POST_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS
- -E
- copy_if_different
- ${BUILT_QUICKTIME_PLUGIN}
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin
- COMMENT "Copying Quicktime Plugin to the runtime folder."
- )
-
- #*******************************
- # Copy media plugin support dlls
- # Debug config runtime files required for the plugins
- set(plugins_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug")
- set(plugins_debug_files
- libeay32.dll
- qtcored4.dll
- qtguid4.dll
- qtnetworkd4.dll
- qtopengld4.dll
- qtwebkitd4.dll
- ssleay32.dll
- )
- copy_if_different(
- ${plugins_debug_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Debug/llplugin"
- out_targets
- ${plugins_debug_files}
- )
- set(media_plugin_targets ${media_plugin_targets} ${out_targets})
-
- # Release & ReleaseDebInfo config runtime files required for the plugins
- set(plugins_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
- set(plugins_release_files
- libeay32.dll
- qtcore4.dll
- qtgui4.dll
- qtnetwork4.dll
- qtopengl4.dll
- qtwebkit4.dll
- ssleay32.dll
- )
- copy_if_different(
- ${plugins_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin"
- out_targets
- ${plugins_release_files}
- )
- set(media_plugin_targets ${media_plugin_targets} ${out_targets})
-
- copy_if_different(
- ${plugins_release_src_dir}
- "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin"
- out_targets
- ${plugins_release_files}
- )
- set(media_plugin_targets ${media_plugin_targets} ${out_targets})
-
- add_custom_target(copy_media_plugin_libs ALL
- DEPENDS
- ${media_plugin_targets}
- )
-
- add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} POST_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS
- -E
- copy_directory
- ${CMAKE_BINARY_DIR}/test_apps/llplugintest/${CMAKE_CFG_INTDIR}/imageformats
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin/imageformats
- COMMENT "Copying llpluging imageformat libs."
- )
-
- add_dependencies(${VIEWER_BINARY_NAME} llmediaplugintest copy_media_plugin_libs)
-
-endif (WINDOWS)
-
+# -*- cmake -*- + +project(viewer) + +include(00-Common) +include(Boost) +include(BuildVersion) +include(DBusGlib) +include(DirectX) +include(ELFIO) +include(FMOD) +include(OPENAL) +include(FindOpenGL) +include(LLAudio) +include(LLCharacter) +include(LLCommon) +include(LLImage) +include(LLImageJ2COJ) +include(LLInventory) +include(LLMath) +include(LLMessage) +include(LLPlugin) +include(LLPrimitive) +include(LLRender) +include(LLUI) +include(LLVFS) +include(LLWindow) +include(LLXML) +include(LLXUIXML) +include(LScript) +include(Linking) +include(NDOF) +include(GooglePerfTools) +include(TemplateCheck) +include(UI) +include(UnixInstall) +include(LLKDU) +include(ViewerMiscLibs) +include(LLLogin) +include(CMakeCopyIfDifferent) + +include_directories( + ${DBUSGLIB_INCLUDE_DIRS} + ${ELFIO_INCLUDE_DIR} + ${LLAUDIO_INCLUDE_DIRS} + ${LLCHARACTER_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLINVENTORY_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLMESSAGE_INCLUDE_DIRS} + ${LLPLUGIN_INCLUDE_DIRS} + ${LLPRIMITIVE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLUI_INCLUDE_DIRS} + ${LLVFS_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} + ${LLXML_INCLUDE_DIRS} + ${LLXUIXML_INCLUDE_DIRS} + ${LSCRIPT_INCLUDE_DIRS} + ${LSCRIPT_INCLUDE_DIRS}/lscript_compile + ${LLLOGIN_INCLUDE_DIRS} + ) + +set(viewer_SOURCE_FILES + llaccordionctrl.cpp + llaccordionctrltab.cpp + llagent.cpp + llagentaccess.cpp + llagentdata.cpp + llagentlanguage.cpp + llagentlistener.cpp + llagentpicksinfo.cpp + llagentpilot.cpp + llagentui.cpp + llagentwearables.cpp + llanimstatelabels.cpp + llappearancemgr.cpp + llappviewer.cpp + llappviewerlistener.cpp + llassetuploadqueue.cpp + llassetuploadresponders.cpp + llaudiosourcevo.cpp + llavataractions.cpp + llavatariconctrl.cpp + llavatarlist.cpp + llavatarlistitem.cpp + llavatarpropertiesprocessor.cpp + llbottomtray.cpp + llbox.cpp + llbreadcrumbview.cpp + llcallbacklist.cpp + llcallingcard.cpp + llcapabilitylistener.cpp + llcaphttpsender.cpp + llchannelmanager.cpp + llchatbar.cpp + llchathistory.cpp + llchatitemscontainerctrl.cpp + llchatmsgbox.cpp + llchiclet.cpp + llclassifiedinfo.cpp + llclassifiedstatsresponder.cpp + llcloud.cpp + llcolorswatch.cpp + llcommandhandler.cpp + llcommandlineparser.cpp + llcompilequeue.cpp + llconfirmationmanager.cpp + llcurrencyuimanager.cpp + llcylinder.cpp + lldateutil.cpp + lldebugmessagebox.cpp + lldebugview.cpp + lldelayedgestureerror.cpp + lldirpicker.cpp + lldndbutton.cpp + lldrawable.cpp + lldrawpool.cpp + lldrawpoolalpha.cpp + lldrawpoolavatar.cpp + lldrawpoolbump.cpp + lldrawpoolground.cpp + lldrawpoolsimple.cpp + lldrawpoolsky.cpp + lldrawpoolterrain.cpp + lldrawpooltree.cpp + lldrawpoolwater.cpp + lldrawpoolwlsky.cpp + lldriverparam.cpp + lldynamictexture.cpp + llemote.cpp + lleventinfo.cpp + lleventnotifier.cpp + lleventpoll.cpp + llexpandabletextbox.cpp + llface.cpp + llfasttimerview.cpp + llfavoritesbar.cpp + llfeaturemanager.cpp + llfilepicker.cpp + llfirstuse.cpp + llflexibleobject.cpp + llfloaterabout.cpp + llfloateractivespeakers.cpp + llfloateranimpreview.cpp + llfloaterauction.cpp + llfloateravatarpicker.cpp + llfloateravatartextures.cpp + llfloaterbeacons.cpp + llfloaterbuildoptions.cpp + llfloaterbulkpermission.cpp + llfloaterbump.cpp + llfloaterbuy.cpp + llfloaterbuycontents.cpp + llfloaterbuycurrency.cpp + llfloaterbuyland.cpp + llfloatercall.cpp + llfloatercamera.cpp + llfloaterchat.cpp + llfloaterchatterbox.cpp + llfloatercolorpicker.cpp + llfloatercustomize.cpp + llfloaterdaycycle.cpp + llfloaterenvsettings.cpp + llfloaterfonttest.cpp + llfloaterfriends.cpp + llfloatergesture.cpp + llfloatergodtools.cpp + llfloatergroupinvite.cpp + llfloatergroups.cpp + llfloaterhandler.cpp + llfloaterhardwaresettings.cpp + llfloaterhelpbrowser.cpp + llfloaterhud.cpp + llfloaterimagepreview.cpp + llfloaterinspect.cpp + llfloaterinventory.cpp + llfloaterjoystick.cpp + llfloaterlagmeter.cpp + llfloaterland.cpp + llfloaterlandholdings.cpp + llfloatermap.cpp + llfloatermediabrowser.cpp + llfloatermediasettings.cpp + llfloatermemleak.cpp + llfloaternamedesc.cpp + llfloaternearbymedia.cpp + llfloaternotificationsconsole.cpp + llfloateropenobject.cpp + llfloaterparcel.cpp + llfloaterpay.cpp + llfloaterperms.cpp + llfloaterpostcard.cpp + llfloaterpostprocess.cpp + llfloaterpreference.cpp + llfloaterproperties.cpp + llfloaterregioninfo.cpp + llfloaterreporter.cpp + llfloaterscriptdebug.cpp + llfloatersearch.cpp + llfloatersellland.cpp + llfloatersettingsdebug.cpp + llfloatersnapshot.cpp + llfloatertelehub.cpp + llfloatertestinspectors.cpp + llfloatertestlistview.cpp + llfloatertools.cpp + llfloatertopobjects.cpp + llfloatertos.cpp + llfloateruipreview.cpp + llfloaterurldisplay.cpp + llfloaterurlentry.cpp + llfloatervoicedevicesettings.cpp + llfloaterwater.cpp + llfloaterwhitelistentry.cpp + llfloaterwindlight.cpp + llfloaterworldmap.cpp + llfoldertype.cpp + llfolderview.cpp + llfolderviewitem.cpp + llfollowcam.cpp + llfriendcard.cpp + llgesturemgr.cpp + llglsandbox.cpp + llgroupactions.cpp + llgrouplist.cpp + llgroupmgr.cpp + llgroupnotify.cpp + llhomelocationresponder.cpp + llhudeffect.cpp + llhudeffectbeam.cpp + llhudeffectlookat.cpp + llhudeffectpointat.cpp + llhudeffecttrail.cpp + llhudicon.cpp + llhudmanager.cpp + llhudobject.cpp + llhudrender.cpp + llhudtext.cpp + llhudview.cpp + llimcontrolpanel.cpp + llimfloater.cpp + llimhandler.cpp + llimpanel.cpp + llimview.cpp + llinspect.cpp + llinspectavatar.cpp + llinspectgroup.cpp + llinspectobject.cpp + llinventorybridge.cpp + llinventoryclipboard.cpp + llinventoryfilter.cpp + llinventoryfunctions.cpp + llinventorymodel.cpp + llinventorypanel.cpp + llinventorysubtreepanel.cpp + lljoystickbutton.cpp + lllandmarkactions.cpp + lllandmarklist.cpp + lllistbrowser.cpp + lllistview.cpp + lllocaltextureobject.cpp + lllocationhistory.cpp + lllocationinputctrl.cpp + lllogchat.cpp + llloginhandler.cpp + lllogininstance.cpp + llmanip.cpp + llmaniprotate.cpp + llmanipscale.cpp + llmaniptranslate.cpp + llmapresponders.cpp + llmediactrl.cpp + llmediadataclient.cpp + llmediaremotectrl.cpp + llmemoryview.cpp + llmenucommands.cpp + llmetricperformancetester.cpp + llmimetypes.cpp + llmorphview.cpp + llmoveview.cpp + llmutelist.cpp + llnamebox.cpp + llnameeditor.cpp + llnamelistctrl.cpp + llnavigationbar.cpp + llnearbychat.cpp + llnearbychatbar.cpp + llnearbychathandler.cpp + llnetmap.cpp + llnotificationalerthandler.cpp + llnotificationgrouphandler.cpp + llnotificationmanager.cpp + llnotificationscripthandler.cpp + llnotificationtiphandler.cpp + llnotify.cpp + lloutputmonitorctrl.cpp + lloverlaybar.cpp + llpanelappearance.cpp + llpanelappearancetab.cpp + llpanelavatar.cpp + llpanelavatarrow.cpp + llpanelavatartag.cpp + llpanelblockedlist.cpp + llpanelclassified.cpp + llpanelcontents.cpp + llpaneleditwearable.cpp + llpanelevent.cpp + llpanelface.cpp + llpanelgroup.cpp + llpanelgroupgeneral.cpp + llpanelgroupinvite.cpp + llpanelgrouplandmoney.cpp + llpanelgroupnotices.cpp + llpanelgrouproles.cpp + llpanelimcontrolpanel.cpp + llpanelland.cpp + llpanellandaudio.cpp + llpanellandmarks.cpp + llpanellandmedia.cpp + llpanellogin.cpp + llpanellookinfo.cpp + llpanellooks.cpp + llpanelmaininventory.cpp + llpanelmedia.cpp + llpanelmediasettingsgeneral.cpp + llpanelmediasettingspermissions.cpp + llpanelmediasettingssecurity.cpp + llpanelmeprofile.cpp + llpanelobject.cpp + llpanelobjectinventory.cpp + llpanelpeople.cpp + llpanelpeoplemenus.cpp + llpanelpermissions.cpp + llpanelpick.cpp + llpanelpicks.cpp + llpanelplace.cpp + llpanelplaceinfo.cpp + llpanelplaces.cpp + llpanelplacestab.cpp + llpanelprimmediacontrols.cpp + llpanelprofile.cpp + llpanelprofileview.cpp + llpanelshower.cpp + llpanelteleporthistory.cpp + llpanelvolume.cpp + llparcelselection.cpp + llparticipantlist.cpp + llpatchvertexarray.cpp + llplacesinventorybridge.cpp + llpolymesh.cpp + llpolymorph.cpp + llpreview.cpp + llpreviewanim.cpp + llpreviewgesture.cpp + llpreviewnotecard.cpp + llpreviewscript.cpp + llpreviewsound.cpp + llpreviewtexture.cpp + llproductinforequest.cpp + llprogressview.cpp + llrecentpeople.cpp + llregionposition.cpp + llremoteparcelrequest.cpp + llsavedsettingsglue.cpp + llscreenchannel.cpp + llscrollingpanelparam.cpp + llsearchcombobox.cpp + llsearchhistory.cpp + llselectmgr.cpp + llsidepanelinventory.cpp + llsidepanelobjectinfo.cpp + llsidetray.cpp + llsidetraypanelcontainer.cpp + llsky.cpp + llslurl.cpp + llspatialpartition.cpp + llspeakers.cpp + llsplitbutton.cpp + llsprite.cpp + llstartup.cpp + llstatusbar.cpp + llstylemap.cpp + llsurface.cpp + llsurfacepatch.cpp + llsyswellitem.cpp + llsyswellwindow.cpp + llteleporthistory.cpp + llteleporthistorystorage.cpp + lltexglobalcolor.cpp + lltexlayer.cpp + lltexlayerparams.cpp + lltextureatlas.cpp + lltextureatlasmanager.cpp + lltexturecache.cpp + lltexturectrl.cpp + lltexturefetch.cpp + lltextureview.cpp + lltoast.cpp + lltoastalertpanel.cpp + lltoastgroupnotifypanel.cpp + lltoastimpanel.cpp + lltoastnotifypanel.cpp + lltoastpanel.cpp + lltool.cpp + lltoolbar.cpp + lltoolbrush.cpp + lltoolcomp.cpp + lltooldraganddrop.cpp + lltoolface.cpp + lltoolfocus.cpp + lltoolgrab.cpp + lltoolgun.cpp + lltoolindividual.cpp + lltoolmgr.cpp + lltoolmorph.cpp + lltoolobjpicker.cpp + lltoolpie.cpp + lltoolpipette.cpp + lltoolplacer.cpp + lltoolselect.cpp + lltoolselectland.cpp + lltoolselectrect.cpp + lltracker.cpp + lltransientdockablefloater.cpp + lltransientfloatermgr.cpp + lluilistener.cpp + lluploaddialog.cpp + llurl.cpp + llurldispatcher.cpp + llurlhistory.cpp + llurllineeditorctrl.cpp + llurlsimstring.cpp + llurlwhitelist.cpp + llvectorperfoptions.cpp + llviewchildren.cpp + llviewerassetstorage.cpp + llvieweraudio.cpp + llviewercamera.cpp + llviewercontrol.cpp + llviewercontrollistener.cpp + llviewerdisplay.cpp + llviewerfloaterreg.cpp + llviewergenericmessage.cpp + llviewergesture.cpp + llviewerhelp.cpp + llviewerhelputil.cpp + llviewerinventory.cpp + llviewerjoint.cpp + llviewerjointattachment.cpp + llviewerjointmesh.cpp + llviewerjointmesh_sse.cpp + llviewerjointmesh_sse2.cpp + llviewerjointmesh_vec.cpp + llviewerjoystick.cpp + llviewerkeyboard.cpp + llviewerlayer.cpp + llviewermedia.cpp + llviewermedia_streamingaudio.cpp + llviewermediafocus.cpp + llviewermenu.cpp + llviewermenufile.cpp + llviewermessage.cpp + llviewernetwork.cpp + llviewerobject.cpp + llviewerobjectlist.cpp + llviewerparcelmedia.cpp + llviewerparcelmediaautoplay.cpp + llviewerparcelmgr.cpp + llviewerparceloverlay.cpp + llviewerpartsim.cpp + llviewerpartsource.cpp + llviewerregion.cpp + llviewershadermgr.cpp + llviewerstats.cpp + llviewertexteditor.cpp + llviewertexture.cpp + llviewertextureanim.cpp + llviewertexturelist.cpp + llviewerthrottle.cpp + llviewervisualparam.cpp + llviewerwindow.cpp + llviewerwindowlistener.cpp + llvlcomposition.cpp + llvlmanager.cpp + llvoavatar.cpp + llvoavatardefines.cpp + llvoavatarself.cpp + llvocache.cpp + llvoclouds.cpp + llvograss.cpp + llvoground.cpp + llvoicechannel.cpp + llvoiceclient.cpp + llvoicecontrolpanel.cpp + llvoiceremotectrl.cpp + llvoicevisualizer.cpp + llvoinventorylistener.cpp + llvopartgroup.cpp + llvosky.cpp + llvosurfacepatch.cpp + llvotextbubble.cpp + llvotree.cpp + llvovolume.cpp + llvowater.cpp + llvowlsky.cpp + llwatchdog.cpp + llwaterparammanager.cpp + llwaterparamset.cpp + llwearable.cpp + llwearabledictionary.cpp + llwearablelist.cpp + llweb.cpp + llwind.cpp + llwlanimator.cpp + llwldaycycle.cpp + llwlparammanager.cpp + llwlparamset.cpp + llworld.cpp + llworldmap.cpp + llworldmapview.cpp + llxmlrpclistener.cpp + llxmlrpctransaction.cpp + noise.cpp + pipeline.cpp + ) + +set(VIEWER_BINARY_NAME "secondlife-bin" CACHE STRING + "The name of the viewer executable to create.") + +if (LINUX) + # We can't set these flags for Darwin, because they get passed to + # the PPC compiler. Ugh. + + set_source_files_properties( + llviewerjointmesh_sse.cpp + PROPERTIES COMPILE_FLAGS "-msse -mfpmath=sse" + ) + set_source_files_properties( + llviewerjointmesh_sse2.cpp + PROPERTIES COMPILE_FLAGS "-msse2 -mfpmath=sse" + ) +endif (LINUX) + +set(viewer_HEADER_FILES + CMakeLists.txt + ViewerInstall.cmake + llaccordionctrl.h + llaccordionctrltab.h + llagent.h + llagentaccess.h + llagentdata.h + llagentlanguage.h + llagentlistener.h + llagentpicksinfo.h + llagentpilot.h + llagentui.h + llagentwearables.h + llanimstatelabels.h + llappearance.h + llappearancemgr.h + llappviewer.h + llappviewerlistener.h + llassetuploadqueue.h + llassetuploadresponders.h + llaudiosourcevo.h + llavataractions.h + llavatariconctrl.h + llavatarlist.h + llavatarlistitem.h + llavatarpropertiesprocessor.h + llbottomtray.h + llbox.h + llbreadcrumbview.h + llcallbacklist.h + llcallingcard.h + llcapabilitylistener.h + llcapabilityprovider.h + llcaphttpsender.h + llchannelmanager.h + llchatbar.h + llchathistory.h + llchatitemscontainerctrl.h + llchatmsgbox.h + llchiclet.h + llclassifiedinfo.h + llclassifiedstatsresponder.h + llcloud.h + llcolorswatch.h + llcommandhandler.h + llcommandlineparser.h + llcompilequeue.h + llconfirmationmanager.h + llcurrencyuimanager.h + llcylinder.h + lldateutil.h + lldebugmessagebox.h + lldebugview.h + lldelayedgestureerror.h + lldirpicker.h + lldndbutton.h + lldrawable.h + lldrawpool.h + lldrawpoolalpha.h + lldrawpoolavatar.h + lldrawpoolbump.h + lldrawpoolclouds.h + lldrawpoolground.h + lldrawpoolsimple.h + lldrawpoolsky.h + lldrawpoolterrain.h + lldrawpooltree.h + lldrawpoolwater.h + lldrawpoolwlsky.h + lldriverparam.h + lldynamictexture.h + llemote.h + lleventinfo.h + lleventnotifier.h + lleventpoll.h + llexpandabletextbox.h + llface.h + llfasttimerview.h + llfavoritesbar.h + llfeaturemanager.h + llfilepicker.h + llfirstuse.h + llflexibleobject.h + llfloaterabout.h + llfloateractivespeakers.h + llfloateranimpreview.h + llfloaterauction.h + llfloateravatarpicker.h + llfloateravatartextures.h + llfloaterbeacons.h + llfloaterbuildoptions.h + llfloaterbulkpermission.h + llfloaterbump.h + llfloaterbuy.h + llfloaterbuycontents.h + llfloaterbuycurrency.h + llfloaterbuyland.h + llfloatercall.h + llfloatercamera.h + llfloaterchat.h + llfloaterchatterbox.h + llfloatercolorpicker.h + llfloatercustomize.h + llfloaterdaycycle.h + llfloaterenvsettings.h + llfloaterfonttest.h + llfloaterfriends.h + llfloatergesture.h + llfloatergodtools.h + llfloatergroupinvite.h + llfloatergroups.h + llfloaterhandler.h + llfloaterhardwaresettings.h + llfloaterhelpbrowser.h + llfloaterhud.h + llfloaterimagepreview.h + llfloaterinspect.h + llfloaterinventory.h + llfloaterjoystick.h + llfloaterlagmeter.h + llfloaterland.h + llfloaterlandholdings.h + llfloatermap.h + llfloatermediabrowser.h + llfloatermediasettings.h + llfloatermemleak.h + llfloaternamedesc.h + llfloaternearbymedia.h + llfloaternotificationsconsole.h + llfloateropenobject.h + llfloaterparcel.h + llfloaterpay.h + llfloaterperms.h + llfloaterpostcard.h + llfloaterpostprocess.h + llfloaterpreference.h + llfloaterproperties.h + llfloaterregioninfo.h + llfloaterreporter.h + llfloaterscriptdebug.h + llfloatersearch.h + llfloatersellland.h + llfloatersettingsdebug.h + llfloatersnapshot.h + llfloatertelehub.h + llfloatertestinspectors.h + llfloatertestlistview.h + llfloatertools.h + llfloatertopobjects.h + llfloatertos.h + llfloateruipreview.h + llfloaterurldisplay.h + llfloaterurlentry.h + llfloatervoicedevicesettings.h + llfloaterwater.h + llfloaterwhitelistentry.h + llfloaterwindlight.h + llfloaterworldmap.h + llfoldertype.h + llfolderview.h + llfoldervieweventlistener.h + llfolderviewitem.h + llfollowcam.h + llfriendcard.h + llgesturemgr.h + llgroupactions.h + llgrouplist.h + llgroupmgr.h + llgroupnotify.h + llhomelocationresponder.h + llhudeffect.h + llhudeffectbeam.h + llhudeffectlookat.h + llhudeffectpointat.h + llhudeffecttrail.h + llhudicon.h + llhudmanager.h + llhudobject.h + llhudrender.h + llhudtext.h + llhudview.h + llimcontrolpanel.h + llimfloater.h + llimpanel.h + llimview.h + llinspect.h + llinspectavatar.h + llinspectgroup.h + llinspectobject.h + llinventorybridge.h + llinventoryclipboard.h + llinventoryfilter.h + llinventoryfunctions.h + llinventorymodel.h + llinventorypanel.h + llinventorysubtreepanel.h + lljoystickbutton.h + lllandmarkactions.h + lllandmarklist.h + lllightconstants.h + lllistbrowser.h + lllistview.h + lllocaltextureobject.h + lllocationhistory.h + lllocationinputctrl.h + lllogchat.h + llloginhandler.h + lllogininstance.h + llmanip.h + llmaniprotate.h + llmanipscale.h + llmaniptranslate.h + llmapresponders.h + llmediactrl.h + llmediadataclient.h + llmediaremotectrl.h + llmemoryview.h + llmenucommands.h + llmetricperformancetester.h + llmimetypes.h + llmorphview.h + llmoveview.h + llmutelist.h + llnamebox.h + llnameeditor.h + llnamelistctrl.h + llnavigationbar.h + llnearbychat.h + llnearbychatbar.h + llnearbychathandler.h + llnetmap.h + llnotificationhandler.h + llnotificationmanager.h + llnotify.h + lloutputmonitorctrl.h + lloverlaybar.h + llpanelappearance.h + llpanelappearancetab.h + llpanelavatar.h + llpanelavatarrow.h + llpanelavatartag.h + llpanelblockedlist.h + llpanelclassified.h + llpanelcontents.h + llpaneleditwearable.h + llpanelevent.h + llpanelface.h + llpanelgroup.h + llpanelgroupgeneral.h + llpanelgroupinvite.h + llpanelgrouplandmoney.h + llpanelgroupnotices.h + llpanelgrouproles.h + llpanelimcontrolpanel.h + llpanelland.h + llpanellandaudio.h + llpanellandmarks.h + llpanellandmedia.h + llpanellogin.h + llpanellookinfo.h + llpanellooks.h + llpanelmaininventory.h + llpanelmedia.h + llpanelmediasettingsgeneral.h + llpanelmediasettingspermissions.h + llpanelmediasettingssecurity.h + llpanelmeprofile.h + llpanelobject.h + llpanelobjectinventory.h + llpanelpeople.h + llpanelpeoplemenus.h + llpanelpermissions.h + llpanelpick.h + llpanelpicks.h + llpanelplace.h + llpanelplaceinfo.h + llpanelplaces.h + llpanelplacestab.h + llpanelprimmediacontrols.h + llpanelprofile.h + llpanelprofileview.h + llpanelshower.h + llpanelteleporthistory.h + llpanelvolume.h + llparcelselection.h + llparticipantlist.h + llpatchvertexarray.h + llplacesinventorybridge.h + llpolymesh.h + llpolymorph.h + llpreview.h + llpreviewanim.h + llpreviewgesture.h + llpreviewnotecard.h + llpreviewscript.h + llpreviewsound.h + llpreviewtexture.h + llproductinforequest.h + llprogressview.h + llrecentpeople.h + llregionposition.h + llremoteparcelrequest.h + llresourcedata.h + llrootview.h + llsavedsettingsglue.h + llscreenchannel.h + llscrollingpanelparam.h + llsearchcombobox.h + llsearchhistory.h + llselectmgr.h + llsidepanelinventory.h + llsidepanelobjectinfo.h + llsidetray.h + llsidetraypanelcontainer.h + llsky.h + llslurl.h + llspatialpartition.h + llspeakers.h + llsplitbutton.h + llsprite.h + llstartup.h + llstatusbar.h + llstylemap.h + llsurface.h + llsurfacepatch.h + llsyswellitem.h + llsyswellwindow.h + lltable.h + llteleporthistory.h + llteleporthistorystorage.h + lltexglobalcolor.h + lltexlayer.h + lltexlayerparams.h + lltextureatlas.h + lltextureatlasmanager.h + lltexturecache.h + lltexturectrl.h + lltexturefetch.h + lltextureview.h + lltoast.h + lltoastalertpanel.h + lltoastgroupnotifypanel.h + lltoastimpanel.h + lltoastnotifypanel.h + lltoastpanel.h + lltool.h + lltoolbar.h + lltoolbrush.h + lltoolcomp.h + lltooldraganddrop.h + lltoolface.h + lltoolfocus.h + lltoolgrab.h + lltoolgun.h + lltoolindividual.h + lltoolmgr.h + lltoolmorph.h + lltoolobjpicker.h + lltoolpie.h + lltoolpipette.h + lltoolplacer.h + lltoolselect.h + lltoolselectland.h + lltoolselectrect.h + lltracker.h + lltransientdockablefloater.h + lltransientfloatermgr.h + lluiconstants.h + lluilistener.h + lluploaddialog.h + llurl.h + llurldispatcher.h + llurlhistory.h + llurllineeditorctrl.h + llurlsimstring.h + llurlwhitelist.h + llvectorperfoptions.h + llviewchildren.h + llviewerassetstorage.h + llvieweraudio.h + llviewerbuild.h + llviewercamera.h + llviewercontrol.h + llviewercontrollistener.h + llviewerdisplay.h + llviewerfloaterreg.h + llviewergenericmessage.h + llviewergesture.h + llviewerhelp.h + llviewerinventory.h + llviewerjoint.h + llviewerjointattachment.h + llviewerjointmesh.h + llviewerjoystick.h + llviewerkeyboard.h + llviewerlayer.h + llviewermedia.h + llviewermediafocus.h + llviewermediaobserver.h + llviewermenu.h + llviewermenufile.h + llviewermessage.h + llviewernetwork.h + llviewerobject.h + llviewerobjectlist.h + llviewerparcelmedia.h + llviewerparcelmediaautoplay.h + llviewerparcelmgr.h + llviewerparceloverlay.h + llviewerpartsim.h + llviewerpartsource.h + llviewerprecompiledheaders.h + llviewerregion.h + llviewershadermgr.h + llviewerstats.h + llviewertexteditor.h + llviewertexture.h + llviewertextureanim.h + llviewertexturelist.h + llviewerthrottle.h + llviewervisualparam.h + llviewerwindow.h + llviewerwindowlistener.h + llvlcomposition.h + llvlmanager.h + llvoavatar.h + llvoavatardefines.h + llvoavatarself.h + llvocache.h + llvoclouds.h + llvograss.h + llvoground.h + llvoicechannel.h + llvoiceclient.h + llvoicecontrolpanel.h + llvoiceremotectrl.h + llvoicevisualizer.h + llvoinventorylistener.h + llvopartgroup.h + llvosky.h + llvosurfacepatch.h + llvotextbubble.h + llvotree.h + llvotreenew.h + llvovolume.h + llvowater.h + llvowlsky.h + llwatchdog.h + llwaterparammanager.h + llwaterparamset.h + llwearable.h + llwearabledictionary.h + llwearablelist.h + llweb.h + llwind.h + llwindebug.h + llwlanimator.h + llwldaycycle.h + llwlparammanager.h + llwlparamset.h + llworld.h + llworldmap.h + llworldmapview.h + llxmlrpclistener.h + llxmlrpctransaction.h + macmain.h + noise.h + pipeline.h + randgauss.h + VertexCache.h + VorbisFramework.h + ) + +source_group("CMake Rules" FILES ViewerInstall.cmake) + +if (DARWIN) + LIST(APPEND viewer_SOURCE_FILES llappviewermacosx.cpp) + + find_library(AGL_LIBRARY AGL) + find_library(APPKIT_LIBRARY AppKit) + find_library(COCOA_LIBRARY Cocoa) + find_library(IOKIT_LIBRARY IOKit) + + set(viewer_LIBRARIES + ${COCOA_LIBRARY} + ${AGL_LIBRARY} + ${IOKIT_LIBRARY} + ) + + # Add resource files to the project. + set(viewer_RESOURCE_FILES + secondlife.icns + macview.r + gpu_table.txt + Info-SecondLife.plist + SecondLife.nib/ + # CMake doesn't seem to support Xcode language variants well just yet + English.lproj/InfoPlist.strings + English.lproj/language.txt + German.lproj/language.txt + Japanese.lproj/language.txt + Korean.lproj/language.txt + ) + set_source_files_properties( + ${viewer_RESOURCE_FILES} + PROPERTIES + HEADER_FILE_ONLY TRUE + #MACOSX_PACKAGE_LOCATION Resources #don't do this! this tells cmake to copy the files. + ) + SOURCE_GROUP("Resources" FILES ${viewer_RESOURCE_FILES}) + list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES}) +endif (DARWIN) + +if (LINUX) + LIST(APPEND viewer_SOURCE_FILES llappviewerlinux.cpp) + LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp) + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") + + set(viewer_LIBRARIES + Xinerama + ) +endif (LINUX) + +if (WINDOWS) + list(APPEND viewer_SOURCE_FILES + llappviewerwin32.cpp + llwindebug.cpp + ) + + list(APPEND viewer_HEADER_FILES + llappviewerwin32.h + llwindebug.h + ) + + # precompiled header configuration + # llviewerprecompiledheaders.cpp generates + # the .pch file. + # All sources added to viewer_SOURCE_FILES + # at this point use it. + set_source_files_properties(llviewerprecompiledheaders.cpp + PROPERTIES + COMPILE_FLAGS "/Ycllviewerprecompiledheaders.h" + ) + foreach( src_file ${viewer_SOURCE_FILES} ) + set_source_files_properties( + ${src_file} + PROPERTIES + COMPILE_FLAGS "/Yullviewerprecompiledheaders.h" + ) + endforeach( src_file ${viewer_SOURCE_FILES} ) + list(APPEND viewer_SOURCE_FILES llviewerprecompiledheaders.cpp) + # llstartup.cpp needs special symbols for audio libraries, so it resets + # COMPILE_FLAGS below. Make sure it maintains precompiled header settings. + set(LLSTARTUP_COMPILE_FLAGS + "${LLSTARTUP_COMPILE_FLAGS} /Yullviewerprecompiledheaders.h") + + # Add resource files to the project. + # viewerRes.rc is the only buildable file, but + # the rest are all dependencies of it. + set(viewer_RESOURCE_FILES + res/arrow.cur + res/arrowcop.cur + res/arrowcopmulti.cur + res/arrowdrag.cur + res/circleandline.cur + res/icon1.ico + res/llarrow.cur + res/llarrowdrag.cur + res/llarrowdragmulti.cur + res/llarrowlocked.cur + res/llgrablocked.cur + res/llno.cur + res/llnolocked.cur + res/lltoolcamera.cur + res/lltoolcreate.cur + res/lltoolfocus.cur + res/lltoolgrab.cur + res/lltoolland.cur + res/lltoolpan.cur + res/lltoolpipette.cur + res/lltoolrotate.cur + res/lltoolscale.cur + res/lltooltranslate.cur + res/lltoolzoomin.cur + res/lltoolzoomout.cur + res/ll_icon.BMP + res/ll_icon.ico + res/resource.h + res/toolpickobject.cur + res/toolpickobject2.cur + res/toolpickobject3.cur + res/toolpipette.cur + ) + + set_source_files_properties(${viewer_RESOURCE_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + + set(viewer_RESOURCE_FILES + res/viewerRes.rc + ${viewer_RESOURCE_FILES} + ) + + SOURCE_GROUP("Resource Files" FILES ${viewer_RESOURCE_FILES}) + + if (NOT STANDALONE) + list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES}) + endif (NOT STANDALONE) + + find_library(DINPUT_LIBRARY dinput8 ${DIRECTX_LIBRARY_DIR}) + find_library(DXGUID_LIBRARY dxguid ${DIRECTX_LIBRARY_DIR}) + mark_as_advanced( + DINPUT_LIBRARY + DXGUID_LIBRARY + ) + + set(viewer_LIBRARIES + ${WINDOWS_LIBRARIES} + comdlg32 + ${DINPUT_LIBRARY} + ${DXGUID_LIBRARY} + kernel32 + odbc32 + odbccp32 + ole32 + oleaut32 + opengl32 + shell32 + Vfw32 + winspool + ) + + find_library(INTEL_MEMOPS_LIBRARY + NAMES ll_intel_memops + PATHS + optimized ${ARCH_PREBUILT_DIRS_RELEASE} + debug ${ARCH_PREBUILT_DIRS_DEBUG} + ) + mark_as_advanced(INTEL_MEMOPS_LIBRARY) + + if (INTEL_MEMOPS_LIBRARY) + list(APPEND viewer_LIBRARIES ${INTEL_MEMOPS_LIBRARY}) + endif (INTEL_MEMOPS_LIBRARY) + + use_prebuilt_binary(dbghelp) +endif (WINDOWS) + +# Add the xui files. This is handy for searching for xui elements +# from within the IDE. +set(viewer_XUI_FILES + skins/default/colors.xml + skins/default/textures/textures.xml + + + + ) +file(GLOB DEFAULT_XUI_FILE_GLOB_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en/*.xml) +list(APPEND viewer_XUI_FILES ${DEFAULT_XUI_FILE_GLOB_LIST}) + +file(GLOB DEFAULT_WIDGET_FILE_GLOB_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en/widgets/*.xml) +list(APPEND viewer_XUI_FILES ${DEFAULT_WIDGET_FILE_GLOB_LIST}) + +file(GLOB SILVER_XUI_FILE_GLOB_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/skins/silver/xui/en-us/*.xml) +list(APPEND viewer_XUI_FILES ${SILVER_XUI_FILE_GLOB_LIST}) + +# Cannot append empty lists in CMake, wait until we have files here. +#file(GLOB SILVER_WIDGET_FILE_GLOB_LIST +# ${CMAKE_CURRENT_SOURCE_DIR}/skins/silver/xui/en-us/widgets/*.xml) +#list(APPEND viewer_XUI_FILES ${SILVER_WIDGET_FILE_GLOB_LIST}) + +list(SORT viewer_XUI_FILES) + +source_group("XUI Files" FILES ${viewer_XUI_FILES}) + +set_source_files_properties(${viewer_XUI_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND viewer_SOURCE_FILES ${viewer_XUI_FILES}) + +set(viewer_APPSETTINGS_FILES + app_settings/anim.ini + app_settings/cmd_line.xml + app_settings/grass.xml + app_settings/high_graphics.xml + app_settings/keys.ini + app_settings/keywords.ini + app_settings/logcontrol.xml + app_settings/low_graphics.xml + app_settings/mid_graphics.xml + app_settings/settings.xml + app_settings/settings_crash_behavior.xml + app_settings/settings_files.xml + app_settings/settings_per_account.xml + app_settings/std_bump.ini + app_settings/trees.xml + app_settings/ultra_graphics.xml + app_settings/viewerart.xml + ${CMAKE_SOURCE_DIR}/../etc/message.xml + ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg + ) + +use_prebuilt_binary(artwork-common) + +source_group("App Settings" FILES ${viewer_APPSETTINGS_FILES}) + +set_source_files_properties(${viewer_APPSETTINGS_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND viewer_SOURCE_FILES ${viewer_APPSETTINGS_FILES}) + +set(viewer_CHARACTER_FILES + character/attentions.xml + character/attentionsN.xml + character/avatar_lad.xml + character/avatar_skeleton.xml + character/genepool.xml + ) + +source_group("Character File" FILES ${viewer_CHARACTER_FILES}) + +set_source_files_properties(${viewer_CHARACTER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) +if (NOT STANDALONE) + list(APPEND viewer_SOURCE_FILES ${viewer_CHARACTER_FILES}) +endif (NOT STANDALONE) + +if (WINDOWS) + file(GLOB viewer_INSTALLER_FILES installers/windows/*.nsi) + + source_group("Installer Files" FILES ${viewer_INSTALLER_FILES}) + + set_source_files_properties(${viewer_INSTALLER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + + list(APPEND viewer_SOURCE_FILES ${viewer_INSTALLER_FILES}) +endif (WINDOWS) + +if (OPENAL) + set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL") +endif (OPENAL) + +if (FMOD) + set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMOD") + + if (DARWIN) + set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp) + add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES}) + set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY}) + set_target_properties( + fmodwrapper + PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path/../Resources" + LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp" + ) + set(FMODWRAPPER_LIBRARY fmodwrapper) + target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES}) + else (DARWIN) + # fmodwrapper unnecessary on linux or windows + set(FMODWRAPPER_LIBRARY ${FMOD_LIBRARY}) + endif (DARWIN) +endif (FMOD) + +set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") + +list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES}) + +set_source_files_properties(${viewer_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +add_executable(${VIEWER_BINARY_NAME} + WIN32 + MACOSX_BUNDLE + ${viewer_SOURCE_FILES} + ) +check_message_template(${VIEWER_BINARY_NAME}) + +if (LLKDU_LIBRARY) + add_dependencies(${VIEWER_BINARY_NAME} ${LLKDU_LIBRARY}) +endif (LLKDU_LIBRARY) + +# add package files +file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST + ${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py) +list(APPEND EVENT_HOST_SCRIPTS ${EVENT_HOST_SCRIPT_GLOB_LIST}) + +set(PACKAGE OFF CACHE BOOL + "Add a package target that builds an installer package.") + +if (WINDOWS) + if(MSVC71) + set(release_flags "/MAP:Release/${VIEWER_BINARY_NAME}.map /MAPINFO:LINES") + else(MSVC71) + set(release_flags "/MAP:Release/${VIEWER_BINARY_NAME}.map") + endif(MSVC71) + + set_target_properties(${VIEWER_BINARY_NAME} + PROPERTIES + # *TODO -reenable this once we get server usage sorted out + #LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:\"__tcmalloc\"" + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO" + LINK_FLAGS_RELEASE ${release_flags} + ) + + # sets the 'working directory' for debugging from visual studio. + if (NOT UNATTENDED) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} PRE_BUILD + COMMAND ${CMAKE_SOURCE_DIR}/tools/vstool/vstool.exe + ARGS + --solution + ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.sln + --workingdir + ${VIEWER_BINARY_NAME} + ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Setting the ${VIEWER_BINARY_NAME} working directory for debugging." + ) + endif (NOT UNATTENDED) + + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} PRE_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/messages/message_template.msg + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings/message_template.msg + COMMENT "Copying message_template.msg to the runtime folder." + ) + + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} PRE_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${CMAKE_CURRENT_SOURCE_DIR}/../../etc/message.xml + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings/message.xml + COMMENT "Copying message.xml to the runtime folder." + ) + + if(WINDOWS) + # Copy Win Libs... + # This happens at build time, not config time. We can't glob files in this cmake. + # *FIX:Mani Write a sub script to glob the files... + # *FIX:Mani Use actually dependencies rather than bulk copy. + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} PRE_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_directory + ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR} + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} + COMMENT "Copying staged dlls." + ) + + add_dependencies(${VIEWER_BINARY_NAME} stage_third_party_libs llcommon) + if(LLKDU_LIBRARY) + # kdu may not exist! + add_dependencies(${VIEWER_BINARY_NAME} llkdu) + endif(LLKDU_LIBRARY) + endif(WINDOWS) + + if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts) + add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts) + endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts) + + add_custom_command( + OUTPUT ${CMAKE_CFG_INTDIR}/touched.bat + COMMAND ${PYTHON_EXECUTABLE} + ARGS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + --configuration=${CMAKE_CFG_INTDIR} + --channel=${VIEWER_CHANNEL} + --login_channel=${VIEWER_LOGIN_CHANNEL} + --grid=${GRID} + --source=${CMAKE_CURRENT_SOURCE_DIR} + --artwork=${ARTWORK_DIR} + --build=${CMAKE_CURRENT_BINARY_DIR} + --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} + --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/touched.bat + DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + ) + + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) + + if (PACKAGE) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2 + COMMAND ${PYTHON_EXECUTABLE} + ARGS + ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CFG_INTDIR} + + DEPENDS + lleventhost + ${EVENT_HOST_SCRIPTS} + ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py) + + add_custom_target(package ALL + DEPENDS + ${CMAKE_CFG_INTDIR}/touched.bat) + # temporarily disable packaging of event_host until hg subrepos get + # sorted out on the parabuild cluster... + #${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2) + add_dependencies(package windows-updater windows-crash-logger) + + + endif (PACKAGE) +endif (WINDOWS) + +target_link_libraries(${VIEWER_BINARY_NAME} + ${LLAUDIO_LIBRARIES} + ${LLCHARACTER_LIBRARIES} + ${LLIMAGE_LIBRARIES} + ${LLIMAGEJ2COJ_LIBRARIES} + ${LLINVENTORY_LIBRARIES} + ${LLMESSAGE_LIBRARIES} + ${LLPLUGIN_LIBRARIES} + ${LLPRIMITIVE_LIBRARIES} + ${LLRENDER_LIBRARIES} + ${FREETYPE_LIBRARIES} + ${LLUI_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLWINDOW_LIBRARIES} + ${LLXML_LIBRARIES} + ${LLXUIXML_LIBRARIES} + ${LSCRIPT_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${NDOF_LIBRARY} + ${viewer_LIBRARIES} + ${BOOST_PROGRAM_OPTIONS_LIBRARY} + ${BOOST_REGEX_LIBRARY} + ${DBUSGLIB_LIBRARIES} + ${OPENGL_LIBRARIES} + ${FMODWRAPPER_LIBRARY} + ${OPENGL_LIBRARIES} + ${SDL_LIBRARY} + ${SMARTHEAP_LIBRARY} + ${UI_LIBRARIES} + ${WINDOWS_LIBRARIES} + ${XMLRPCEPI_LIBRARIES} + ${ELFIO_LIBRARIES} + ${LLLOGIN_LIBRARIES} + ${GOOGLE_PERFTOOLS_LIBRARIES} + ) + +build_version(viewer) + +set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH + "Path to artwork files.") + + +if (LINUX) + add_custom_command( + OUTPUT secondlife-stripped + COMMAND strip + ARGS --strip-debug -o secondlife-stripped ${VIEWER_BINARY_NAME} + DEPENDS ${VIEWER_BINARY_NAME} + ) + + set(product SecondLife-${ARCH}-${viewer_VERSION}) + + add_custom_command( + OUTPUT ${product}.tar.bz2 + COMMAND ${PYTHON_EXECUTABLE} + ARGS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + --grid=${GRID} + --channel=${VIEWER_CHANNEL} + --login_channel=${VIEWER_LOGIN_CHANNEL} + --installer_name=${product} + --arch=${ARCH} + --source=${CMAKE_CURRENT_SOURCE_DIR} + --artwork=${ARTWORK_DIR} + --build=${CMAKE_CURRENT_BINARY_DIR} + --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged + --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched + DEPENDS secondlife-stripped ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + ) + + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer010 media_plugin_webkit) + + if (NOT INSTALL) + add_custom_target(package ALL DEPENDS ${product}.tar.bz2) + add_dependencies(package linux-crash-logger-strip-target) + add_dependencies(package linux-updater-strip-target) + endif (NOT INSTALL) +endif (LINUX) + +if (DARWIN) + set(product "Second Life") + set_target_properties( + ${VIEWER_BINARY_NAME} + PROPERTIES + OUTPUT_NAME "${product}" + MACOSX_BUNDLE_INFO_STRING "info string - localize me" + MACOSX_BUNDLE_ICON_FILE "secondlife.icns" + MACOSX_BUNDLE_GUI_IDENTIFIER "Second Life" + MACOSX_BUNDLE_LONG_VERSION_STRING "ververver" + MACOSX_BUNDLE_BUNDLE_NAME "Second Life" + MACOSX_BUNDLE_SHORT_VERSION_STRING "asdf" + MACOSX_BUNDLE_BUNDLE_VERSION "asdf" + MACOSX_BUNDLE_COPYRIGHT "copyright linden lab 2007 - localize me and run me through a legal wringer" + ) + + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${PYTHON_EXECUTABLE} + ARGS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + --grid=${GRID} + --actions=copy + --configuration=${CMAKE_CFG_INTDIR} + --source=${CMAKE_CURRENT_SOURCE_DIR} + --artwork=${ARTWORK_DIR} + --build=${CMAKE_CURRENT_BINARY_DIR} + --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app + DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + ) + + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) + + if (PACKAGE) + add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME}) + add_dependencies(package mac-updater mac-crash-logger) + + add_custom_command( + TARGET package POST_BUILD + COMMAND ${PYTHON_EXECUTABLE} + ARGS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + --grid=${GRID} + --configuration=${CMAKE_CFG_INTDIR} + --channel=${VIEWER_CHANNEL} + --login_channel=${VIEWER_LOGIN_CHANNEL} + --source=${CMAKE_CURRENT_SOURCE_DIR} + --artwork=${ARTWORK_DIR} + --build=${CMAKE_CURRENT_BINARY_DIR} + --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app + --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + ) + + + add_custom_command( + TARGET package POST_BUILD + COMMAND ${PYTHON_EXECUTABLE} + ARGS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + --grid=${GRID} + --configuration=${CMAKE_CFG_INTDIR} + --channel=${VIEWER_CHANNEL} + --login_channel=${VIEWER_LOGIN_CHANNEL} + --source=${CMAKE_CURRENT_SOURCE_DIR} + --artwork=${ARTWORK_DIR} + --build=${CMAKE_CURRENT_BINARY_DIR} + --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app + --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + ) + + endif (PACKAGE) +endif (DARWIN) + +if (INSTALL) + include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) +endif (INSTALL) + +# To add a viewer unit test, just add the test .cpp file below +# This creates a separate test project per file listed. +include(LLAddBuildTest) +SET(viewer_TEST_SOURCE_FILES + llagentaccess.cpp + lldateutil.cpp + llmediadataclient.cpp + llviewerhelputil.cpp + lllogininstance.cpp + ) +set_source_files_properties( + ${viewer_TEST_SOURCE_FILES} + PROPERTIES + LL_TEST_ADDITIONAL_SOURCE_FILES llviewerprecompiledheaders.cpp + ) +LL_ADD_PROJECT_UNIT_TESTS(${VIEWER_BINARY_NAME} "${viewer_TEST_SOURCE_FILES}") + +#set(TEST_DEBUG on) +set(test_sources llcapabilitylistener.cpp llviewerprecompiledheaders.cpp) +set(test_libs + ${LLMESSAGE_LIBRARIES} + ${WINDOWS_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${GOOGLEMOCK_LIBRARIES} + ) + +LL_ADD_INTEGRATION_TEST(llcapabilitylistener + "${test_sources}" + "${test_libs}" + ${PYTHON_EXECUTABLE} + "${CMAKE_SOURCE_DIR}/llmessage/tests/test_llsdmessage_peer.py" + ) + +#ADD_VIEWER_BUILD_TEST(llmemoryview viewer) + + +# Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py +if (WINDOWS) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + make_directory + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin + COMMENT "Creating llplugin dir." + ) + + get_target_property(BUILT_SLPLUGIN SLPlugin LOCATION) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${BUILT_SLPLUGIN} + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} + COMMENT "Copying SLPlugin executable to the runtime folder." + ) + + get_target_property(BUILT_WEBKIT_PLUGIN media_plugin_webkit LOCATION) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${BUILT_WEBKIT_PLUGIN} + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin + COMMENT "Copying WebKit Plugin to the runtime folder." + ) + + get_target_property(BUILT_QUICKTIME_PLUGIN media_plugin_quicktime LOCATION) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${BUILT_QUICKTIME_PLUGIN} + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin + COMMENT "Copying Quicktime Plugin to the runtime folder." + ) + + #******************************* + # Copy media plugin support dlls + # Debug config runtime files required for the plugins + set(plugins_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") + set(plugins_debug_files + libeay32.dll + qtcored4.dll + qtguid4.dll + qtnetworkd4.dll + qtopengld4.dll + qtwebkitd4.dll + ssleay32.dll + ) + copy_if_different( + ${plugins_debug_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/Debug/llplugin" + out_targets + ${plugins_debug_files} + ) + set(media_plugin_targets ${media_plugin_targets} ${out_targets}) + + # Release & ReleaseDebInfo config runtime files required for the plugins + set(plugins_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") + set(plugins_release_files + libeay32.dll + qtcore4.dll + qtgui4.dll + qtnetwork4.dll + qtopengl4.dll + qtwebkit4.dll + ssleay32.dll + ) + copy_if_different( + ${plugins_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin" + out_targets + ${plugins_release_files} + ) + set(media_plugin_targets ${media_plugin_targets} ${out_targets}) + + copy_if_different( + ${plugins_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin" + out_targets + ${plugins_release_files} + ) + set(media_plugin_targets ${media_plugin_targets} ${out_targets}) + + add_custom_target(copy_media_plugin_libs ALL + DEPENDS + ${media_plugin_targets} + ) + + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_directory + ${CMAKE_BINARY_DIR}/test_apps/llplugintest/${CMAKE_CFG_INTDIR}/imageformats + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin/imageformats + COMMENT "Copying llpluging imageformat libs." + ) + + add_dependencies(${VIEWER_BINARY_NAME} llmediaplugintest copy_media_plugin_libs) + +endif (WINDOWS) + diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6bc95b9cdb..c4722b772e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3631,6 +3631,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>IMShowControlPanel</key> + <map> + <key>Comment</key> + <string>Show IM Control Panel</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>IgnoreAllNotifications</key> <map> <key>Comment</key> @@ -4875,7 +4886,7 @@ <key>Value</key> <integer>10</integer> </map> - <key>ToastOpaqueTime</key> + <key>ToastFadingTime</key> <map> <key>Comment</key> <string>Number of seconds while a toast is fading </string> @@ -4887,6 +4898,29 @@ <integer>1</integer> </map> <key>StartUpToastLifeTime</key> + <key>NearbyToastFadingTime</key> + <map> + <key>Comment</key> + <string>Number of seconds while a nearby chat toast is fading </string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>3</integer> + </map> + <key>NearbyToastLifeTime</key> + <map> + <key>Comment</key> + <string>Number of seconds while a nearby chat toast exists</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>23</integer> + </map> + <key>StartUpToastLifeTime</key> <map> <key>Comment</key> <string>Number of seconds while a StartUp toast exist</string> @@ -8812,13 +8846,13 @@ <key>UICloseBoxFromTop</key> <map> <key>Comment</key> - <string>Size of UI floater close box from top</string> + <string>Distance from top of floater to top of close box icon, pixels</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>S32</string> <key>Value</key> - <real>1</real> + <real>5</real> </map> <key>UIExtraTriangleHeight</key> <map> @@ -8853,17 +8887,6 @@ <key>Value</key> <real>16</real> </map> - <key>UIFloaterHeaderSize</key> - <map> - <key>Comment</key> - <string>Size of UI floater header size</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <real>18</real> - </map> <key>UIFloaterHPad</key> <map> <key>Comment</key> @@ -8886,16 +8909,16 @@ <key>Value</key> <integer>0</integer> </map> - <key>UIFloaterVPad</key> + <key>UIFloaterTitleVPad</key> <map> <key>Comment</key> - <string>Size of UI floater vertical pad</string> + <string>Distance from top of floater to top of title string, pixels</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>S32</string> <key>Value</key> - <real>6</real> + <real>7</real> </map> <key>UIImgDefaultEyesUUID</key> <map> @@ -9007,17 +9030,6 @@ <key>Value</key> <string>5748decc-f629-461c-9a36-a35a221fe21f</string> </map> - <key>UIImgDefaultTattooUUID</key> - <map> - <key>Comment</key> - <string /> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>5748decc-f629-461c-9a36-a35a221fe21f</string> - </map> <key>UIImgDefaultUnderwearUUID</key> <map> <key>Comment</key> diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 1d4a78f025..81c899312d 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1986,6 +1986,17 @@ bool LLAgentWearables::canWearableBeRemoved(const LLWearable* wearable) const return !(((type == WT_SHAPE) || (type == WT_SKIN) || (type == WT_HAIR) || (type == WT_EYES)) && (getWearableCount(type) <= 1) ); } +void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL set_by_user) +{ + for( S32 type = 0; type < WT_COUNT; ++type ) + { + for (S32 count = 0; count < (S32)getWearableCount((EWearableType)type); ++count) + { + LLWearable *wearable = getWearable((EWearableType)type,count); + wearable->animateParams(delta, set_by_user); + } + } +} void LLAgentWearables::updateServer() { diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 667cb94552..97de785c87 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -79,6 +79,8 @@ public: // Note: False for shape, skin, eyes, and hair, unless you have MORE than 1. bool canWearableBeRemoved(const LLWearable* wearable) const; + + void animateAllWearableParams(F32 delta, BOOL set_by_user); //-------------------------------------------------------------------- // Accessors diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 06c9171d67..873215169e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -238,8 +238,6 @@ U32 gFrameCount = 0; U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground LLPumpIO* gServicePump = NULL; -BOOL gPacificDaylightTime = FALSE; - U64 gFrameTime = 0; F32 gFrameTimeSeconds = 0.f; F32 gFrameIntervalSeconds = 0.f; diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index d970aa6ae1..73256a8fe6 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -301,10 +301,6 @@ extern U32 gForegroundFrameCount; extern LLPumpIO* gServicePump; -// Is the Pacific time zone (aka server time zone) -// currently in daylight savings time? -extern BOOL gPacificDaylightTime; - extern U64 gFrameTime; // The timestamp of the most-recently-processed frame extern F32 gFrameTimeSeconds; // Loses msec precision after ~4.5 hours... extern F32 gFrameIntervalSeconds; // Elapsed time between current and previous gFrameTimeSeconds diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index ebcda13dd4..b56e8d1ec2 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -155,6 +155,8 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p) mPriority = LLViewerFetchedTexture::BOOST_ICON; LLRect rect = p.rect; + mDrawWidth = llmax(32, rect.getWidth()) ; + mDrawHeight = llmax(32, rect.getHeight()) ; static LLUICachedControl<S32> llavatariconctrl_symbol_hpad("UIAvatariconctrlSymbolHPad", 2); static LLUICachedControl<S32> llavatariconctrl_symbol_vpad("UIAvatariconctrlSymbolVPad", 2); @@ -193,7 +195,6 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p) LLIconCtrl::setValue("default_profile_picture.j2c"); } - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("AvatarIcon.Action", boost::bind(&LLAvatarIconCtrl::onAvatarIconContextMenuItemClicked, this, _2)); diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index e93d0dfa50..65a2b8b5e6 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -37,11 +37,15 @@ // newview #include "llcallingcard.h" // for LLAvatarTracker #include "llcachename.h" +#include "llrecentpeople.h" #include "llvoiceclient.h" #include "llviewercontrol.h" // for gSavedSettings static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list"); +// Last interaction time update period. +static const F32 LIT_UPDATE_PERIOD = 5; + // Maximum number of avatars that can be added to a list in one pass. // Used to limit time spent for avatar list update per frame. static const unsigned ADD_LIMIT = 50; @@ -74,19 +78,34 @@ static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_ LLAvatarList::Params::Params() : ignore_online_status("ignore_online_status", false) +, show_last_interaction_time("show_last_interaction_time", false) { } LLAvatarList::LLAvatarList(const Params& p) : LLFlatListView(p) , mIgnoreOnlineStatus(p.ignore_online_status) +, mShowLastInteractionTime(p.show_last_interaction_time) , mContextMenu(NULL) , mDirty(true) // to force initial update +, mLITUpdateTimer(NULL) { setCommitOnSelectionChange(true); // Set default sort order. setComparator(&NAME_COMPARATOR); + + if (mShowLastInteractionTime) + { + mLITUpdateTimer = new LLTimer(); + mLITUpdateTimer->setTimerExpirySec(0); // zero to force initial update + mLITUpdateTimer->start(); + } +} + +LLAvatarList::~LLAvatarList() +{ + delete mLITUpdateTimer; } void LLAvatarList::setShowIcons(std::string param_name) @@ -105,6 +124,12 @@ void LLAvatarList::draw() if (mDirty) refresh(); + + if (mShowLastInteractionTime && mLITUpdateTimer->hasExpired()) + { + updateLastInteractionTimes(); + mLITUpdateTimer->setTimerExpirySec(LIT_UPDATE_PERIOD); // restart the timer + } } void LLAvatarList::setNameFilter(const std::string& filter) @@ -218,12 +243,12 @@ void LLAvatarList::refresh() void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos) { LLAvatarListItem* item = new LLAvatarListItem(); - item->showStatus(false); item->showInfoBtn(true); item->showSpeakingIndicator(true); item->setName(name); item->setAvatarId(id, mIgnoreOnlineStatus); item->setOnline(mIgnoreOnlineStatus ? true : is_online); + item->showLastInteractionTime(mShowLastInteractionTime); item->setContextMenu(mContextMenu); item->childSetVisible("info_btn", false); @@ -279,6 +304,54 @@ void LLAvatarList::computeDifference( vadded.erase(it, vadded.end()); } +static std::string format_secs(S32 secs) +{ + // *TODO: reinventing the wheel? + // *TODO: i18n + static const int LL_AL_MIN = 60; + static const int LL_AL_HOUR = LL_AL_MIN * 60; + static const int LL_AL_DAY = LL_AL_HOUR * 24; + static const int LL_AL_WEEK = LL_AL_DAY * 7; + static const int LL_AL_MONTH = LL_AL_DAY * 31; + static const int LL_AL_YEAR = LL_AL_DAY * 365; + + std::string s; + + if (secs >= LL_AL_YEAR) + s = llformat("%dy", secs / LL_AL_YEAR); + else if (secs >= LL_AL_MONTH) + s = llformat("%dmon", secs / LL_AL_MONTH); + else if (secs >= LL_AL_WEEK) + s = llformat("%dw", secs / LL_AL_WEEK); + else if (secs >= LL_AL_DAY) + s = llformat("%dd", secs / LL_AL_DAY); + else if (secs >= LL_AL_HOUR) + s = llformat("%dh", secs / LL_AL_HOUR); + else if (secs >= LL_AL_MIN) + s = llformat("%dm", secs / LL_AL_MIN); + else + s = llformat("%ds", secs); + + return s; +} + +// Refresh shown time of our last interaction with all listed avatars. +void LLAvatarList::updateLastInteractionTimes() +{ + S32 now = (S32) LLDate::now().secondsSinceEpoch(); + std::vector<LLPanel*> items; + getItems(items); + + for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++) + { + // *TODO: error handling + LLAvatarListItem* item = static_cast<LLAvatarListItem*>(*it); + S32 secs_since = now - (S32) LLRecentPeople::instance().getDate(item->getAvatarId()).secondsSinceEpoch(); + if (secs_since >= 0) + item->setLastInteractionTime(format_secs(secs_since)); + } +} + bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const { const LLAvatarListItem* avatar_item1 = dynamic_cast<const LLAvatarListItem*>(item1); diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index f60f1f00f3..8f2f0249a6 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -37,6 +37,8 @@ #include "llavatarlistitem.h" +class LLTimer; + /** * Generic list of avatars. * @@ -56,11 +58,12 @@ public: struct Params : public LLInitParam::Block<Params, LLFlatListView::Params> { Optional<bool> ignore_online_status; // show all items as online + Optional<bool> show_last_interaction_time; // show most recent interaction time. *HACK: move this to a derived class Params(); }; LLAvatarList(const Params&); - virtual ~LLAvatarList() {} + virtual ~LLAvatarList(); virtual void draw(); // from LLView @@ -85,13 +88,16 @@ protected: const std::vector<LLUUID>& vnew, std::vector<LLUUID>& vadded, std::vector<LLUUID>& vremoved); + void updateLastInteractionTimes(); private: bool mIgnoreOnlineStatus; + bool mShowLastInteractionTime; bool mDirty; bool mShowIcons; + LLTimer* mLITUpdateTimer; // last interaction time update timer std::string mIconParamName; std::string mNameFilter; uuid_vector_t mIDs; diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 4ecb9537ba..8464430501 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -48,7 +48,7 @@ LLAvatarListItem::LLAvatarListItem() : LLPanel(), mAvatarIcon(NULL), mAvatarName(NULL), - mStatus(NULL), + mLastInteractionTime(NULL), mSpeakingIndicator(NULL), mInfoBtn(NULL), mProfileBtn(NULL), @@ -74,8 +74,8 @@ BOOL LLAvatarListItem::postBuild() { mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon"); mAvatarName = getChild<LLTextBox>("avatar_name"); - mStatus = getChild<LLTextBox>("avatar_status"); - + mLastInteractionTime = getChild<LLTextBox>("last_interaction"); + mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator"); mInfoBtn = getChild<LLButton>("info_btn"); mProfileBtn = getChild<LLButton>("profile_btn"); @@ -97,12 +97,6 @@ BOOL LLAvatarListItem::postBuild() rect.setLeftTopAndSize(mName->getRect().mLeft, mName->getRect().mTop, mName->getRect().getWidth() + 30, mName->getRect().getHeight()); mName->setRect(rect); - if(mStatus) - { - rect.setLeftTopAndSize(mStatus->getRect().mLeft + 30, mStatus->getRect().mTop, mStatus->getRect().getWidth(), mStatus->getRect().getHeight()); - mStatus->setRect(rect); - } - if(mLocator) { rect.setLeftTopAndSize(mLocator->getRect().mLeft + 30, mLocator->getRect().mTop, mLocator->getRect().getWidth(), mLocator->getRect().getHeight()); @@ -137,11 +131,6 @@ void LLAvatarListItem::onMouseLeave(S32 x, S32 y, MASK mask) LLPanel::onMouseLeave(x, y, mask); } -void LLAvatarListItem::setStatus(const std::string& status) -{ - mStatus->setValue(status); -} - // virtual, called by LLAvatarTracker void LLAvatarListItem::changed(U32 mask) { @@ -195,6 +184,24 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes) gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3)); } +void LLAvatarListItem::showLastInteractionTime(bool show) +{ + if (show) + return; + + LLRect name_rect = mAvatarName->getRect(); + LLRect time_rect = mLastInteractionTime->getRect(); + + mLastInteractionTime->setVisible(false); + name_rect.mRight += (time_rect.mRight - name_rect.mRight); + mAvatarName->setRect(name_rect); +} + +void LLAvatarListItem::setLastInteractionTime(const std::string& val) +{ + mLastInteractionTime->setValue(val); +} + void LLAvatarListItem::setAvatarIconVisible(bool visible) { // Already done? Then do nothing. @@ -240,21 +247,6 @@ void LLAvatarListItem::onProfileBtnClick() LLAvatarActions::showProfile(mAvatarId); } -void LLAvatarListItem::showStatus(bool show_status) -{ - // *HACK: dirty hack until we can determine correct avatar status (EXT-1076). - - if (show_status) - return; - - LLRect name_rect = mAvatarName->getRect(); - LLRect status_rect = mStatus->getRect(); - - mStatus->setVisible(show_status); - name_rect.mRight += (status_rect.mRight - name_rect.mRight); - mAvatarName->setRect(name_rect); -} - void LLAvatarListItem::setValue( const LLSD& value ) { if (!value.isMap()) return;; diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index a8d3919217..10c0b17005 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -60,10 +60,10 @@ public: virtual void setValue(const LLSD& value); virtual void changed(U32 mask); // from LLFriendObserver - void setStatus(const std::string& status); void setOnline(bool online); void setName(const std::string& name); void setAvatarId(const LLUUID& id, bool ignore_status_changes = false); + void setLastInteractionTime(const std::string& val); void setAvatarIconVisible(bool visible); const LLUUID& getAvatarId() const; @@ -74,7 +74,7 @@ public: void showSpeakingIndicator(bool show) { mSpeakingIndicator->setVisible(show); } void showInfoBtn(bool show_info_btn) {mInfoBtn->setVisible(show_info_btn); } - void showStatus(bool show_status); + void showLastInteractionTime(bool show); void setContextMenu(ContextMenu* menu) { mContextMenu = menu; } @@ -90,7 +90,7 @@ private: LLAvatarIconCtrl* mAvatarIcon; LLTextBox* mAvatarName; - LLTextBox* mStatus; + LLTextBox* mLastInteractionTime; LLOutputMonitorCtrl* mSpeakingIndicator; LLButton* mInfoBtn; diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index aaca568320..e561507e69 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -43,6 +43,8 @@ #include "llagentdata.h" #include "llavataractions.h" #include "lltrans.h" +#include "llfloaterreg.h" +#include "llmutelist.h" static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history"); static const std::string MESSAGE_USERNAME_DATE_SEPARATOR(" ----- "); @@ -77,6 +79,19 @@ public: return LLPanel::handleMouseUp(x,y,mask); } + void onObjectIconContextMenuItemClicked(const LLSD& userdata) + { + std::string level = userdata.asString(); + + if (level == "profile") + { + } + else if (level == "block") + { + LLMuteList::getInstance()->add(LLMute(getAvatarId(), mFrom, LLMute::OBJECT)); + } + } + void onAvatarIconContextMenuItemClicked(const LLSD& userdata) { std::string level = userdata.asString(); @@ -109,11 +124,17 @@ public: LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2)); + registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2)); LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mPopupMenuHandleAvatar = menu->getHandle(); + menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mPopupMenuHandleObject = menu->getHandle(); + + LLPanel* visible_panel = getChild<LLPanel>("im_header"); + visible_panel->setMouseDownCallback(boost::bind(&LLChatHistoryHeader::onHeaderPanelClick, this, _2, _3, _4)); + return LLPanel::postBuild(); } @@ -145,6 +166,12 @@ public: return LLPanel::handleRightMouseDown(x,y,mask); } + + void onHeaderPanelClick(S32 x, S32 y, MASK mask) + { + LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", mAvatarID)); + } + const LLUUID& getAvatarId () const { return mAvatarID;} const std::string& getFirstName() const { return mFirstName; } const std::string& getLastName () const { return mLastName; } @@ -163,7 +190,10 @@ public: LLTextBox* userName = getChild<LLTextBox>("user_name"); if(!chat.mFromName.empty()) + { userName->setValue(chat.mFromName); + mFrom = chat.mFromName; + } else { std::string SL = LLTrans::getString("SECOND_LIFE"); @@ -206,8 +236,12 @@ protected: void showSystemContextMenu(S32 x,S32 y) { } + void showObjectContextMenu(S32 x,S32 y) { + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleObject.get(); + if(menu) + LLMenuGL::showPopup(this, menu, x, y); } void showAvatarContextMenu(S32 x,S32 y) @@ -238,11 +272,13 @@ protected: protected: LLHandle<LLView> mPopupMenuHandleAvatar; + LLHandle<LLView> mPopupMenuHandleObject; LLUUID mAvatarID; EChatSourceType mSourceType; std::string mFirstName; std::string mLastName; + std::string mFrom; }; diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 61a60a24be..bad61101c1 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -37,7 +37,6 @@ #include "llbottomtray.h" #include "llgroupactions.h" #include "lliconctrl.h" -#include "llimpanel.h" // LLFloaterIMPanel #include "llimfloater.h" #include "llimview.h" #include "llfloaterreg.h" @@ -58,8 +57,6 @@ static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t4("chiclet_im_p2p"); static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t5("chiclet_im_group"); S32 LLNotificationChiclet::mUreadSystemNotifications = 0; -S32 LLNotificationChiclet::mUreadIMNotifications = 0; - boost::signals2::signal<LLChiclet* (const LLUUID&), LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > > @@ -100,7 +97,6 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p) // connect counter handlers to the signals connectCounterUpdatersToSignal("notify"); connectCounterUpdatersToSignal("groupnotify"); - connectCounterUpdatersToSignal("notifytoast"); } LLNotificationChiclet::~LLNotificationChiclet() @@ -114,16 +110,8 @@ void LLNotificationChiclet::connectCounterUpdatersToSignal(std::string notificat LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); if(n_handler) { - if(notification_type == "notifytoast") - { - n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::updateUreadIMNotifications, this)); - n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::updateUreadIMNotifications, this)); - } - else - { - n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); - n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); - } + n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); + n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); } } @@ -148,12 +136,6 @@ void LLNotificationChiclet::setToggleState(BOOL toggled) { mButton->setToggleState(toggled); } -void LLNotificationChiclet::updateUreadIMNotifications() -{ - mUreadIMNotifications = gIMMgr->getNumberOfUnreadIM(); - setCounter(mUreadSystemNotifications + mUreadIMNotifications); -} - ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -1398,7 +1380,7 @@ void LLTalkButton::onClick_ShowBtn() LLAvatarListItem* item = new LLAvatarListItem(); - item->showStatus(true); + item->showLastInteractionTime(false); item->showInfoBtn(true); item->showSpeakingIndicator(true); item->reshape(mPrivateCallPanel->getRect().getWidth(), item->getRect().getHeight(), FALSE); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index d1153a075d..6eefd9829f 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -608,10 +608,9 @@ public: /*virtual*/ ~ LLNotificationChiclet(); - // methods for updating a number of unread System or IM notifications - void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications + mUreadIMNotifications); } - void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications + mUreadIMNotifications); } - void updateUreadIMNotifications(); + // methods for updating a number of unread System notifications + void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); } + void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); } void setToggleState(BOOL toggled); protected: @@ -622,7 +621,6 @@ protected: friend class LLUICtrlFactory; static S32 mUreadSystemNotifications; - static S32 mUreadIMNotifications; protected: LLButton* mButton; diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp index 979a1a9a60..c4bfd71999 100644 --- a/indra/newview/llcurrencyuimanager.cpp +++ b/indra/newview/llcurrencyuimanager.cpp @@ -35,6 +35,8 @@ #include "lluictrlfactory.h" #include "lltextbox.h" #include "lllineeditor.h" +#include "llviewercontrol.h" +#include "llversionviewer.h" #include "llcurrencyuimanager.h" @@ -156,6 +158,11 @@ void LLCurrencyUIManager::Impl::updateCurrencyInfo() "secureSessionId", gAgent.getSecureSessionID().asString()); keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy); + keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName")); + keywordArgs.appendInt("viewerMajorVersion", LL_VERSION_MAJOR); + keywordArgs.appendInt("viewerMinorVersion", LL_VERSION_MINOR); + keywordArgs.appendInt("viewerPatchVersion", LL_VERSION_PATCH); + keywordArgs.appendInt("viewerBuildVersion", LL_VERSION_BUILD); LLXMLRPCValue params = LLXMLRPCValue::createArray(); params.append(keywordArgs); @@ -209,7 +216,12 @@ void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password) { keywordArgs.appendString("password", password); } - + keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName")); + keywordArgs.appendInt("viewerMajorVersion", LL_VERSION_MAJOR); + keywordArgs.appendInt("viewerMinorVersion", LL_VERSION_MINOR); + keywordArgs.appendInt("viewerPatchVersion", LL_VERSION_PATCH); + keywordArgs.appendInt("viewerBuildVersion", LL_VERSION_BUILD); + LLXMLRPCValue params = LLXMLRPCValue::createArray(); params.append(keywordArgs); diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 45f4b4fbd0..527656ab6b 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -224,6 +224,7 @@ void LLDriverParam::setAvatar(LLVOAvatar *avatarp) } } *new_param = *this; + new_param->setIsDummy(FALSE); return new_param; } diff --git a/indra/newview/lleventinfo.cpp b/indra/newview/lleventinfo.cpp index 9be45d18fb..aabd7ed997 100644 --- a/indra/newview/lleventinfo.cpp +++ b/indra/newview/lleventinfo.cpp @@ -33,7 +33,6 @@ #include "llviewerprecompiledheaders.h" #include "lleventinfo.h" -#include "llappviewer.h" // for gPacificDaylightTime #include "lluuid.h" #include "message.h" diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 48b5fc11b7..7bc48185e6 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -51,7 +51,7 @@ public: /*virtual*/ void getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { // more label always spans width of text box - width = mEditor.getTextRect().getWidth(); + width = mEditor.getTextRect().getWidth() - mEditor.getHPad(); height = llceil(mStyle->getFont()->getLineHeight()); } /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const @@ -153,6 +153,11 @@ void LLExpandableTextBox::LLTextBoxEx::showExpandText() { if (!mExpanderVisible) { + // make sure we're scrolled to top when collapsing + if (mScroller) + { + mScroller->goToTop(); + } // get fully visible lines std::pair<S32, S32> visible_lines = getVisibleLines(true); S32 last_line = visible_lines.second - 1; diff --git a/indra/newview/llexpandabletextbox.h b/indra/newview/llexpandabletextbox.h index d45527aabb..3fe646c29c 100644 --- a/indra/newview/llexpandabletextbox.h +++ b/indra/newview/llexpandabletextbox.h @@ -69,16 +69,6 @@ protected: virtual S32 getVerticalTextDelta(); /** - * Returns text vertical padding - */ - virtual S32 getVPad() { return mVPad; } - - /** - * Returns text horizontal padding - */ - virtual S32 getHPad() { return mHPad; } - - /** * Shows "More" link */ void showExpandText(); diff --git a/indra/newview/llface.h b/indra/newview/llface.h index d734b327d9..2b134c8c31 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -246,7 +246,7 @@ protected: //atlas LLPointer<LLTextureAtlasSlot> mAtlasInfop ; - BOOL mUsingAtlas ; + BOOL mUsingAtlas ; protected: static BOOL sSafeRenderSelect; diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 216bca8262..fc8790c172 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -704,7 +704,7 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) } if (volume->mLODChanged || volume->mFaceMappingChanged || - volume->mVolumeChanged) + volume->mVolumeChanged || drawable->isState(LLDrawable::REBUILD_MATERIAL)) { volume->regenFaces(); volume->mDrawable->setState(LLDrawable::REBUILD_VOLUME); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 63ea990d14..88658f7b9f 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -39,6 +39,7 @@ #include "llagent.h"
#include "llappviewer.h"
#include "llsecondlifeurls.h"
+#include "llvoiceclient.h"
#include "lluictrlfactory.h"
#include "llviewertexteditor.h"
#include "llviewercontrol.h"
@@ -268,6 +269,7 @@ LLSD LLFloaterAbout::getInfo() info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
bool want_fullname = true;
info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD();
+ info["VIVOX_VERSION"] = gVoiceClient ? gVoiceClient->getAPIVersion() : "Unknown";
// TODO: Implement media plugin version query
info["QT_WEBKIT_VERSION"] = "4.5.2";
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index ccfe7d4b64..8ac7f3fd7e 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -35,6 +35,7 @@ // Viewer includes #include "llagent.h" +#include "llcallingcard.h" #include "llfocusmgr.h" #include "llfloaterreg.h" #include "llviewercontrol.h" @@ -76,6 +77,7 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key) mCloseOnSelect(FALSE) { // LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_picker.xml"); + mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this)); } BOOL LLFloaterAvatarPicker::postBuild() @@ -95,7 +97,11 @@ BOOL LLFloaterAvatarPicker::postBuild() LLScrollListCtrl* nearme = getChild<LLScrollListCtrl>("NearMe"); nearme->setDoubleClickCallback(onBtnSelect, this); childSetCommitCallback("NearMe", onList, this); - + + LLScrollListCtrl* friends = getChild<LLScrollListCtrl>("Friends"); + friends->setDoubleClickCallback(onBtnSelect, this); + childSetCommitCallback("Friends", onList, this); + childSetAction("Select", onBtnSelect, this); childDisable("Select"); @@ -119,6 +125,8 @@ BOOL LLFloaterAvatarPicker::postBuild() center(); + populateFriend(); + return TRUE; } @@ -159,25 +167,37 @@ void LLFloaterAvatarPicker::onBtnSelect(void* userdata) if(self->mCallback) { + std::string acvtive_panel_name; + LLScrollListCtrl* list = NULL; LLPanel* active_panel = self->childGetVisibleTab("ResidentChooserTabs"); - - if(active_panel == self->getChild<LLPanel>("SearchPanel")) + if(active_panel) { - std::vector<std::string> avatar_names; - std::vector<LLUUID> avatar_ids; - getSelectedAvatarData(self->getChild<LLScrollListCtrl>("SearchResults"), avatar_names, avatar_ids); - self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata); + acvtive_panel_name = active_panel->getName(); + } + if(acvtive_panel_name == "SearchPanel") + { + list = self->getChild<LLScrollListCtrl>("SearchResults"); + } + else if(acvtive_panel_name == "NearMePanel") + { + list =self->getChild<LLScrollListCtrl>("NearMe"); + } + else if (acvtive_panel_name == "FriendsPanel") + { + list =self->getChild<LLScrollListCtrl>("Friends"); } - else if(active_panel == self->getChild<LLPanel>("NearMePanel")) + + if(list) { std::vector<std::string> avatar_names; std::vector<LLUUID> avatar_ids; - getSelectedAvatarData(self->getChild<LLScrollListCtrl>("NearMe"), avatar_names, avatar_ids); + getSelectedAvatarData(list, avatar_names, avatar_ids); self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata); } } self->getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE); self->getChild<LLScrollListCtrl>("NearMe")->deselectAllItems(TRUE); + self->getChild<LLScrollListCtrl>("Friends")->deselectAllItems(TRUE); if(self->mCloseOnSelect) { self->mCloseOnSelect = FALSE; @@ -268,6 +288,26 @@ void LLFloaterAvatarPicker::populateNearMe() } } +void LLFloaterAvatarPicker::populateFriend() +{ + LLScrollListCtrl* friends_scroller = getChild<LLScrollListCtrl>("Friends"); + friends_scroller->deleteAllItems(); + LLCollectAllBuddies collector; + LLAvatarTracker::instance().applyFunctor(collector); + LLCollectAllBuddies::buddy_map_t::iterator it; + + + for(it = collector.mOnline.begin(); it!=collector.mOnline.end(); it++) + { + friends_scroller->addStringUUIDItem(it->first, it->second); + } + for(it = collector.mOffline.begin(); it!=collector.mOffline.end(); it++) + { + friends_scroller->addStringUUIDItem(it->first, it->second); + } + friends_scroller->sortByColumnIndex(0, TRUE); +} + void LLFloaterAvatarPicker::draw() { LLFloater::draw(); @@ -289,6 +329,10 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const { return getChild<LLScrollListCtrl>("NearMe")->getFirstSelectedIndex() >= 0; } + else if(active_panel == getChild<LLPanel>("FriendsPanel")) + { + return getChild<LLScrollListCtrl>("Friends")->getFirstSelectedIndex() >= 0; + } return FALSE; } @@ -321,6 +365,7 @@ void LLFloaterAvatarPicker::setAllowMultiple(BOOL allow_multiple) { getChild<LLScrollListCtrl>("SearchResults")->setAllowMultipleSelection(allow_multiple); getChild<LLScrollListCtrl>("NearMe")->setAllowMultipleSelection(allow_multiple); + getChild<LLScrollListCtrl>("Friends")->setAllowMultipleSelection(allow_multiple); } // static diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index 85aacb68a5..b8ace985d9 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -67,6 +67,7 @@ private: void onTabChanged(); void populateNearMe(); + void populateFriend(); BOOL visibleItemsSelected() const; // Returns true if any items in the current tab are selected. void find(); diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp index 8b64f913e0..68f06b1e5b 100644 --- a/indra/newview/llfloaterbump.cpp +++ b/indra/newview/llfloaterbump.cpp @@ -40,7 +40,6 @@ #include "llsd.h" #include "lluictrlfactory.h" #include "llviewermessage.h" -#include "llappviewer.h" // gPacificDaylightTime ///---------------------------------------------------------------------------- /// Class LLFloaterBump diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index dca0773139..d1317f7c36 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -268,8 +268,8 @@ void LLFloaterCamera::updateState() LLRect controls_rect; if (childGetRect(CONTROLS, controls_rect)) { - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); - static S32 height = controls_rect.getHeight() - floater_header_size; + S32 floater_header_size = getHeaderHeight(); + S32 height = controls_rect.getHeight() - floater_header_size; S32 newHeight = rect.getHeight(); if (showControls) diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index 86abebe7ce..ed14079ae9 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -182,13 +182,7 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& void log_chat_text(const LLChat& chat) { - std::string histstr; - if (gSavedPerAccountSettings.getBOOL("LogTimestamp")) - histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + chat.mText; - else - histstr = chat.mText; - - LLLogChat::saveHistory(std::string("chat"),histstr); + LLLogChat::saveHistory(std::string("chat"), chat.mFromName, chat.mFromID, chat.mText); } // static void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file) @@ -476,7 +470,7 @@ void LLFloaterChat::loadHistory() } //static -void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , std::string line, void* userdata) +void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , const LLSD& line, void* userdata) { switch (type) { @@ -485,9 +479,10 @@ void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , std::string l // *TODO: nice message from XML file here break; case LLLogChat::LOG_LINE: + case LLLogChat::LOG_LLSD: { LLChat chat; - chat.mText = line; + chat.mText = line["message"].asString(); get_text_color(chat); addChatHistory(chat, FALSE); } diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h index 6ba3165d6a..aed82a6781 100644 --- a/indra/newview/llfloaterchat.h +++ b/indra/newview/llfloaterchat.h @@ -78,7 +78,7 @@ public: static void onClickMute(void *data); static void onClickToggleShowMute(LLUICtrl* caller, void *data); static void onClickToggleActiveSpeakers(void* userdata); - static void chatFromLogFile(LLLogChat::ELogLineType type,std::string line, void* userdata); + static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& line, void* userdata); static void loadHistory(); static void* createSpeakersPanel(void* data); static void* createChatPanel(void* data); diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 8e385fca78..73b79d8e13 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -561,7 +561,7 @@ void LLFloaterColorPicker::draw() // create rgb area outline gl_rect_2d ( mRGBViewerImageLeft, mRGBViewerImageTop - mRGBViewerImageHeight, - mRGBViewerImageLeft + mRGBViewerImageWidth, + mRGBViewerImageLeft + mRGBViewerImageWidth + 1, mRGBViewerImageTop, LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ), FALSE ); @@ -591,7 +591,7 @@ void LLFloaterColorPicker::draw() // draw luminance slider outline gl_rect_2d ( mLumRegionLeft, mLumRegionTop - mLumRegionHeight, - mLumRegionLeft + mLumRegionWidth, + mLumRegionLeft + mLumRegionWidth + 1, mLumRegionTop, LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ), FALSE ); @@ -607,7 +607,7 @@ void LLFloaterColorPicker::draw() // draw selected color swatch outline gl_rect_2d ( mSwatchRegionLeft, mSwatchRegionTop - mSwatchRegionHeight, - mSwatchRegionLeft + mSwatchRegionWidth, + mSwatchRegionLeft + mSwatchRegionWidth + 1, mSwatchRegionTop, LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ), FALSE ); diff --git a/indra/newview/llfloatergroupinvite.cpp b/indra/newview/llfloatergroupinvite.cpp index 3598479305..bf484c6343 100644 --- a/indra/newview/llfloatergroupinvite.cpp +++ b/indra/newview/llfloatergroupinvite.cpp @@ -81,7 +81,7 @@ void LLFloaterGroupInvite::impl::closeFloater(void* data) LLFloaterGroupInvite::LLFloaterGroupInvite(const LLUUID& group_id) : LLFloater(group_id) { - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); + S32 floater_header_size = getHeaderHeight(); LLRect contents; mImpl = new impl(group_id); @@ -114,7 +114,8 @@ LLFloaterGroupInvite::~LLFloaterGroupInvite() // static void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, std::vector<LLUUID> *agent_ids) { - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); + const LLFloater::Params& floater_params = LLFloater::getDefaultParams(); + S32 floater_header_size = floater_params.header_height; LLRect contents; // Make sure group_id isn't null diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index f2dff55044..f20fca1258 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -221,7 +221,8 @@ void LLFloaterNotificationConsole::removeChannel(const std::string& name) //static void LLFloaterNotificationConsole::updateResizeLimits() { - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); + const LLFloater::Params& floater_params = LLFloater::getDefaultParams(); + S32 floater_header_size = floater_params.header_height; LLLayoutStack& stack = getChildRef<LLLayoutStack>("notification_channels"); setResizeLimits(getMinWidth(), floater_header_size + HEADER_PADDING + ((NOTIFICATION_PANEL_HEADER_HEIGHT + 3) * stack.getNumPanels())); diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 4c83530f43..bd9798c18e 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -34,6 +34,7 @@ #include "llviewerprecompiledheaders.h" #include "llfloatersearch.h" #include "llmediactrl.h" +#include "llagent.h" LLFloaterSearch::LLFloaterSearch(const LLSD& key) : @@ -117,6 +118,14 @@ void LLFloaterSearch::search(const LLSD &key) std::string search_text = key.has("id") ? key["id"].asString() : ""; url += std::string("?q=") + search_text; + // append the maturity and teen capabilities for this agent + BOOL godlike = gAgent.isGodlike(); + bool mature_enabled = gAgent.canAccessMature() || godlike; + bool adult_enabled = gAgent.canAccessAdult() || godlike; + std::string mature = (mature_enabled) ? "True" : "False"; + std::string teen = (!adult_enabled) ? "True" : "False"; + url += "&t=" + teen + "&m=" + mature; + // and load the URL in the web view mBrowser->navigateTo(url); } diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 9c13e90d2c..3aef15a35c 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -49,6 +49,7 @@ #include "llfloaterreg.h" #include "llfocusmgr.h" #include "llmediaentry.h" +#include "llmediactrl.h" #include "llmenugl.h" #include "llpanelcontents.h" #include "llpanelface.h" @@ -221,6 +222,7 @@ BOOL LLFloaterTools::postBuild() mRadioGroupMove = getChild<LLRadioGroup>("move_radio_group"); mRadioGroupEdit = getChild<LLRadioGroup>("edit_radio_group"); mBtnGridOptions = getChild<LLButton>("Options..."); + mTitleMedia = getChild<LLMediaCtrl>("title_media"); mCheckSelectIndividual = getChild<LLCheckBoxCtrl>("checkbox edit linked parts"); childSetValue("checkbox edit linked parts",(BOOL)gSavedSettings.getBOOL("EditLinkedParts")); @@ -304,6 +306,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key) mCheckSnapToGrid(NULL), mBtnGridOptions(NULL), + mTitleMedia(NULL), mTextGridMode(NULL), mComboGridMode(NULL), mCheckStretchUniform(NULL), @@ -335,7 +338,8 @@ LLFloaterTools::LLFloaterTools(const LLSD& key) mPanelLandInfo(NULL), mTabLand(NULL), - mDirty(TRUE) + mDirty(TRUE), + mNeedMediaTitle(TRUE) { gFloaterTools = this; @@ -440,6 +444,9 @@ void LLFloaterTools::draw() mDirty = FALSE; } + // grab media name/title and update the UI widget + updateMediaTitle(); + // mCheckSelectIndividual->set(gSavedSettings.getBOOL("EditLinkedParts")); LLFloater::draw(); } @@ -736,6 +743,10 @@ void LLFloaterTools::onClose(bool app_quitting) LLViewerJoystick::getInstance()->moveAvatar(false); + // destroy media source used to grab media title + if( mTitleMedia ) + mTitleMedia->unloadMediaSource(); + // Different from handle_reset_view in that it doesn't actually // move the camera if EditCameraMovement is not set. gAgent.resetView(gSavedSettings.getBOOL("EditCameraMovement")); @@ -1108,6 +1119,7 @@ void LLFloaterTools::getMediaState() std::string multi_media_info_str = LLTrans::getString("Multiple Media"); std::string media_title = ""; + mNeedMediaTitle = false; // update UI depending on whether "object" (prim or face) has media // and whether or not you are allowed to edit it. @@ -1123,18 +1135,19 @@ void LLFloaterTools::getMediaState() // Media data is valid if(media_data_get!=default_media_data) { - //TODO: get media title - //media_title = media_data_get->getTitle(); - //LLFloaterMediaSettings::getInstance()->mIdenticalValidMedia = true; + // initial media title is the media URL (until we get the name) media_title = media_data_get.getHomeURL(); + + // kick off a navigate and flag that we need to update the title + navigateToTitleMedia( media_data_get.getHomeURL() ); + mNeedMediaTitle = true; } // else all faces might be empty. - - } else // there' re Different Medias' been set on on the faces. { media_title = multi_media_info_str; + mNeedMediaTitle = false; } childSetEnabled("media_tex", bool_has_media & editable); @@ -1152,17 +1165,20 @@ void LLFloaterTools::getMediaState() if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia) { media_title = multi_media_info_str; + mNeedMediaTitle = false; } else { // Media data is valid if(media_data_get!=default_media_data) { - //TODO: get media title - //media_title = media_data_get->getTitle(); + // initial media title is the media URL (until we get the name) media_title = media_data_get.getHomeURL(); + + // kick off a navigate and flag that we need to update the title + navigateToTitleMedia( media_data_get.getHomeURL() ); + mNeedMediaTitle = true; } - } media_info->setEnabled(false); @@ -1253,12 +1269,63 @@ bool LLFloaterTools::deleteMediaConfirm(const LLSD& notification, const LLSD& re return false; } +////////////////////////////////////////////////////////////////////////////// +// void LLFloaterTools::clearMediaSettings() { LLFloaterMediaSettings::getInstance(); LLFloaterMediaSettings::clearValues(false); } + +////////////////////////////////////////////////////////////////////////////// +// +void LLFloaterTools::navigateToTitleMedia( const std::string url ) +{ + if ( mTitleMedia ) + { + LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin(); + if ( media_plugin ) + { + // if it's a movie, we don't want to hear it + media_plugin->setVolume( 0 ); + }; + mTitleMedia->navigateTo( url ); + }; +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLFloaterTools::updateMediaTitle() +{ + // only get the media name if we need it + if ( ! mNeedMediaTitle ) + return; + + // get plugin impl + LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin(); + if ( media_plugin ) + { + // get the media name (asynchronous - must call repeatedly) + std::string media_title = media_plugin->getMediaName(); + + // only replace the title if what we get contains something + if ( ! media_title.empty() ) + { + // update the UI widget + LLLineEditor* media_title_field = getChild<LLLineEditor>("media_info"); + if ( media_title_field ) + { + media_title_field->setText( media_title ); + + // stop looking for a title when we get one + // FIXME: check this is the right approach + mNeedMediaTitle = false; + }; + }; + }; +} + ////////////////////////////////////////////////////////////////////////////// // void LLFloaterTools::updateMediaSettings() diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index 59acef6071..a3e0cac034 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -51,6 +51,7 @@ class LLRadioGroup; class LLSlider; class LLTabContainer; class LLTextBox; +class LLMediaCtrl; class LLTool; class LLParcelSelection; class LLObjectSelection; @@ -107,6 +108,8 @@ public: void onClickBtnAddMedia(); void onClickBtnEditMedia(); void clearMediaSettings(); + void updateMediaTitle(); + void navigateToTitleMedia( const std::string url ); bool selectedMediaEditable(); private: @@ -182,6 +185,9 @@ public: LLParcelSelectionHandle mParcelSelection; LLObjectSelectionHandle mObjectSelection; + LLMediaCtrl *mTitleMedia; + bool mNeedMediaTitle; + private: BOOL mDirty; diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index ac743df4f1..2fe21f28de 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -865,7 +865,8 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save) } else // if it is a panel... { - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); + const LLFloater::Params& floater_params = LLFloater::getDefaultParams(); + S32 floater_header_size = floater_params.header_height; LLPanel::Params panel_params; LLPanel* panel = LLUICtrlFactory::create<LLPanel>(panel_params); // create a new panel diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index b86795f696..b21df87093 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -235,11 +235,6 @@ BOOL LLIMFloater::postBuild() setTitle(LLIMModel::instance().getName(mSessionID)); setDocked(true); - - if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) - { - LLLogChat::loadHistory(getTitle(), &chatFromLogFile, (void *)this); - } mTypingStart = LLTrans::getString("IM_typing_start_string"); @@ -307,6 +302,8 @@ void LLIMFloater::onSlide() LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel"); im_control_panel->setVisible(!im_control_panel->getVisible()); + gSavedSettings.setBOOL("IMShowControlPanel", im_control_panel->getVisible()); + getChild<LLButton>("slide_left_btn")->setVisible(im_control_panel->getVisible()); getChild<LLButton>("slide_right_btn")->setVisible(!im_control_panel->getVisible()); } @@ -349,6 +346,8 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) LLDockControl::TOP, boost::bind(&LLIMFloater::getAllowedRect, floater, _1))); } + floater->childSetVisible("panel_im_control_panel", gSavedSettings.getBOOL("IMShowControlPanel")); + return floater; } @@ -410,8 +409,6 @@ bool LLIMFloater::toggle(const LLUUID& session_id) { // ensure the list of messages is updated when floater is made visible show(session_id); - // update number of unread notifications in the SysWell - LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications(); return true; } } @@ -453,9 +450,6 @@ void LLIMFloater::updateMessages() { std::list<LLSD> messages; LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1); - std::string agent_name; - - gCacheName->getFullName(gAgentID, agent_name); if (messages.size()) { @@ -464,20 +458,17 @@ void LLIMFloater::updateMessages() std::ostringstream message; std::list<LLSD>::const_reverse_iterator iter = messages.rbegin(); std::list<LLSD>::const_reverse_iterator iter_end = messages.rend(); - for (; iter != iter_end; ++iter) + for (; iter != iter_end; ++iter) { LLSD msg = *iter; - std::string from = msg["from"].asString(); std::string time = msg["time"].asString(); LLUUID from_id = msg["from_id"].asUUID(); + std::string from = from_id != gAgentID ? msg["from"].asString() : LLTrans::getString("You"); std::string message = msg["message"].asString(); LLStyle::Params style_params; style_params.color(chat_color); - if (from == agent_name) - from = LLTrans::getString("You"); - LLChat chat(message); chat.mFromID = from_id; chat.mFromName = from; @@ -657,38 +648,3 @@ void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info) } } -void LLIMFloater::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata) -{ - if (!userdata) return; - - LLIMFloater* self = (LLIMFloater*) userdata; - std::string message = line; - S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions"); - switch (type) - { - case LLLogChat::LOG_EMPTY: - // add warning log enabled message - if (im_log_option!=LOG_CHAT) - { - message = LLTrans::getString("IM_logging_string"); - } - break; - case LLLogChat::LOG_END: - // add log end message - if (im_log_option!=LOG_CHAT) - { - message = LLTrans::getString("IM_logging_string"); - } - break; - case LLLogChat::LOG_LINE: - // just add normal lines from file - break; - default: - // nothing - break; - } - - self->mChatHistory->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor"))); - self->mChatHistory->blockUndo(); -} - diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 3da27ac941..d2aac57ee2 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -106,8 +106,6 @@ private: // gets a rect that bounds possible positions for the LLIMFloater on a screen (EXT-1111) void getAllowedRect(LLRect& rect); - static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata); - // Add the "User is typing..." indicator. void addTypingIndicator(const LLIMInfo* im_info); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index fdbbf2f189..7399f1e1b3 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -182,13 +182,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, // enable line history support for instant message bar mInputEditor->setEnableLineHistory(TRUE); - if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) - { - LLLogChat::loadHistory(mSessionLabel, - &chatFromLogFile, - (void *)this); - } - //*TODO we probably need the same "awaiting message" thing in LLIMFloater LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionUUID); if (!im_session) @@ -978,41 +971,6 @@ void LLFloaterIMPanel::removeTypingIndicator(const LLIMInfo* im_info) } } -//static -void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata) -{ - LLFloaterIMPanel* self = (LLFloaterIMPanel*)userdata; - std::string message = line; - S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions"); - switch (type) - { - case LLLogChat::LOG_EMPTY: - // add warning log enabled message - if (im_log_option!=LOG_CHAT) - { - message = LLTrans::getString("IM_logging_string"); - } - break; - case LLLogChat::LOG_END: - // add log end message - if (im_log_option!=LOG_CHAT) - { - message = LLTrans::getString("IM_logging_string"); - } - break; - case LLLogChat::LOG_LINE: - // just add normal lines from file - break; - default: - // nothing - break; - } - - //self->addHistoryLine(line, LLColor4::grey, FALSE); - self->mHistoryEditor->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor"))); - self->mHistoryEditor->blockUndo(); -} - //static void LLFloaterIMPanel::onKickSpeaker(void* user_data) { diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 39107d9a22..b8f99d45c9 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -127,7 +127,6 @@ public: // Handle other participant in the session typing. void processIMTyping(const LLIMInfo* im_info, BOOL typing); - static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata); private: // Called by UI methods. diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 8a55ab41b9..49fc9d8055 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -135,7 +135,6 @@ LLIMModel::LLIMModel() addNewMsgCallback(toast_callback); } - LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids) : mSessionID(session_id), mName(name), @@ -179,6 +178,9 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionID); mOtherParticipantIsAvatar = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionID); } + + if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) + LLLogChat::loadHistory(mName, &chatFromLogFile, (void *)this); } LLIMModel::LLIMSession::~LLIMSession() @@ -220,6 +222,34 @@ void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_ } } +void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time) +{ + LLSD message; + message["from"] = from; + message["from_id"] = from_id; + message["message"] = utf8_text; + message["time"] = time; + message["index"] = (LLSD::Integer)mMsgs.size(); + + mMsgs.push_front(message); +} + +void LLIMModel::LLIMSession::chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata) +{ + if (!userdata) return; + + LLIMSession* self = (LLIMSession*) userdata; + + if (type == LLLogChat::LOG_LINE) + { + self->addMessage("", LLSD(), msg["message"].asString(), ""); + } + else if (type == LLLogChat::LOG_LLSD) + { + self->addMessage(msg["from"].asString(), msg["from_id"].asUUID(), msg["message"].asString(), msg["time"].asString()); + } +} + LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const { return get_if_there(LLIMModel::instance().sSessionsMap, session_id, @@ -348,39 +378,25 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, return false; } - LLSD message; - message["from"] = from; - message["from_id"] = from_id; - message["message"] = utf8_text; - message["time"] = LLLogChat::timestamp(false); //might want to add date separately - message["index"] = (LLSD::Integer)session->mMsgs.size(); - - session->mMsgs.push_front(message); + session->addMessage(from, from_id, utf8_text, LLLogChat::timestamp(false)); //might want to add date separately return true; - } //*TODO rewrite chat history persistence using LLSD serialization (IB) -bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const std::string& utf8_text) +bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) { S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions"); if (im_log_option != LOG_CHAT) { - std::string histstr; - if (gSavedPerAccountSettings.getBOOL("LogTimestamp")) - histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + from + IM_SEPARATOR + utf8_text; - else - histstr = from + IM_SEPARATOR + utf8_text; - if(im_log_option == LOG_BOTH_TOGETHER) { - LLLogChat::saveHistory(std::string("chat"), histstr); + LLLogChat::saveHistory(std::string("chat"), from, from_id, utf8_text); return true; } else { - LLLogChat::saveHistory(LLIMModel::getInstance()->getName(session_id), histstr); + LLLogChat::saveHistory(LLIMModel::getInstance()->getName(session_id), from, from_id, utf8_text); return true; } } @@ -398,7 +414,7 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co } addToHistory(session_id, from, from_id, utf8_text); - if (log2file) logToFile(session_id, from, utf8_text); + if (log2file) logToFile(session_id, from, from_id, utf8_text); session->mNumUnread++; @@ -1360,14 +1376,9 @@ void LLIMMgr::addMessage( fixed_session_name = session_name; } - bool new_session = !hasSession(session_id); + bool new_session = !hasSession(new_session_id); if (new_session) { - // *NOTE dzaporozhan - // Workaround for critical bug EXT-1918 - - // *TODO - // Investigate cases when session_id == NULL and find solution to handle those cases LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id); } diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index ae8fd355ea..d0bd594df1 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -40,6 +40,7 @@ #include "llinstantmessage.h" #include "lluuid.h" #include "llmultifloater.h" +#include "lllogchat.h" class LLFloaterChatterBox; class LLUUID; @@ -57,6 +58,8 @@ public: virtual ~LLIMSession(); void sessionInitReplyReceived(const LLUUID& new_session_id); + void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time); + static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata); LLUUID mSessionID; std::string mName; @@ -193,8 +196,7 @@ private: /** * Save an IM message into a file */ - //*TODO should also save uuid of a sender - bool logToFile(const LLUUID& session_id, const std::string& from, const std::string& utf8_text); + bool logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text); }; class LLIMSessionObserver diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp index 29cca14a7b..050a61c79b 100644 --- a/indra/newview/llinspectobject.cpp +++ b/indra/newview/llinspectobject.cpp @@ -35,10 +35,12 @@ // Viewer #include "llinspect.h" +#include "llmediaentry.h" #include "llnotifications.h" // *TODO: Eliminate, add LLNotificationsUtil wrapper #include "llselectmgr.h" #include "llslurl.h" #include "llviewermenu.h" // handle_object_touch(), handle_buy() +#include "llviewermedia.h" #include "llviewerobjectlist.h" // to select the requested object // Linden libraries @@ -92,8 +94,10 @@ private: void updateName(LLSelectNode* nodep); void updateDescription(LLSelectNode* nodep); void updatePrice(LLSelectNode* nodep); - void updateCreator(LLSelectNode* nodep); + + void updateMediaCurrentURL(); + void updateSecureBrowsing(); void onClickBuy(); void onClickPay(); @@ -106,13 +110,17 @@ private: private: LLUUID mObjectID; + S32 mObjectFace; + viewer_media_t mMediaImpl; LLSafeHandle<LLObjectSelection> mObjectSelection; }; LLInspectObject::LLInspectObject(const LLSD& sd) : LLInspect( LLSD() ), // single_instance, doesn't really need key - mObjectID(), // set in onOpen() - mObjectSelection() + mObjectID(NULL), // set in onOpen() + mObjectFace(0), + mObjectSelection(NULL), + mMediaImpl(NULL) { // can't make the properties request until the widgets are constructed // as it might return immediately, so do it in postBuild. @@ -139,7 +147,7 @@ BOOL LLInspectObject::postBuild(void) getChild<LLUICtrl>("object_name")->setValue(""); getChild<LLUICtrl>("object_creator")->setValue(""); getChild<LLUICtrl>("object_description")->setValue(""); - + getChild<LLUICtrl>("object_media_url")->setValue(""); // Set buttons invisible until we know what this object can do hideButtons(); @@ -182,7 +190,11 @@ void LLInspectObject::onOpen(const LLSD& data) // Extract appropriate avatar id mObjectID = data["object_id"]; - + + if(data.has("object_face")) + { + mObjectFace = data["object_face"]; + } // Position the inspector relative to the mouse cursor // Similar to how tooltips are positioned // See LLToolTipMgr::createToolTip @@ -213,6 +225,17 @@ void LLInspectObject::onOpen(const LLSD& data) } } functor; mObjectSelection->applyToNodes(&functor); + + // Does this face have media? + const LLTextureEntry* tep = obj->getTE(mObjectFace); + if (!tep) + return; + + const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; + if(!mep) + return; + + mMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); } } @@ -243,6 +266,30 @@ void LLInspectObject::update() updateDescription(nodep); updateCreator(nodep); updatePrice(nodep); + + LLViewerObject* obj = nodep->getObject(); + if(!obj) + return; + + if ( mObjectFace < 0 + || mObjectFace >= obj->getNumTEs() ) + { + return; + } + + // Does this face have media? + const LLTextureEntry* tep = obj->getTE(mObjectFace); + if (!tep) + return; + + const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; + if(!mep) + return; + + mMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); + + updateMediaCurrentURL(); + updateSecureBrowsing(); } void LLInspectObject::hideButtons() @@ -381,6 +428,40 @@ void LLInspectObject::updateDescription(LLSelectNode* nodep) } } +void LLInspectObject::updateMediaCurrentURL() +{ + LLTextBox* textbox = getChild<LLTextBox>("object_media_url"); + std::string media_url = ""; + textbox->setValue(media_url); + textbox->setToolTip(media_url); + + if(mMediaImpl.notNull() && mMediaImpl->hasMedia()) + { + LLStringUtil::format_map_t args; + LLPluginClassMedia* media_plugin = NULL; + media_plugin = mMediaImpl->getMediaPlugin(); + if(media_plugin) + { + if(media_plugin->pluginSupportsMediaTime()) + { + args["[CurrentURL]"] = mMediaImpl->getMediaURL(); + } + else + { + args["[CurrentURL]"] = media_plugin->getLocation(); + } + media_url = LLTrans::getString("CurrentURL", args); + textbox->setText(media_url); + textbox->setToolTip(media_url); + } + } + else + { + textbox->setText(media_url); + textbox->setToolTip(media_url); + } +} + void LLInspectObject::updateCreator(LLSelectNode* nodep) { // final information for display @@ -453,6 +534,40 @@ void LLInspectObject::updatePrice(LLSelectNode* nodep) getChild<LLUICtrl>("price_icon")->setVisible(show_price_icon); } +void LLInspectObject::updateSecureBrowsing() +{ + bool is_secure_browsing = false; + + if(mMediaImpl.notNull() + && mMediaImpl->hasMedia()) + { + LLPluginClassMedia* media_plugin = NULL; + std::string current_url = ""; + media_plugin = mMediaImpl->getMediaPlugin(); + if(media_plugin) + { + if(media_plugin->pluginSupportsMediaTime()) + { + current_url = mMediaImpl->getMediaURL(); + } + else + { + current_url = media_plugin->getLocation(); + } + } + + std::string prefix = std::string("https://"); + std::string test_prefix = current_url.substr(0, prefix.length()); + LLStringUtil::toLower(test_prefix); + if(test_prefix == prefix) + { + is_secure_browsing = true; + } + } + getChild<LLUICtrl>("secure_browsing")->setVisible(is_secure_browsing); +} + + void LLInspectObject::onClickBuy() { handle_buy(); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 55e102b8f3..336025e55e 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1,5149 +1,5149 @@ -/**
- * @file llinventorybridge.cpp
- * @brief Implementation of the Inventory-Folder-View-Bridge classes.
- *
- * $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 <utility> // for std::pair<>
-
-#include "llfloaterinventory.h"
-#include "llinventorybridge.h"
-
-#include "message.h"
-
-#include "llagent.h"
-#include "llagentwearables.h"
-#include "llcallingcard.h"
-#include "llcheckboxctrl.h" // for radio buttons
-#include "llfloaterreg.h"
-#include "llradiogroup.h"
-#include "llspinctrl.h"
-#include "lltextbox.h"
-#include "llui.h"
-
-#include "llviewercontrol.h"
-#include "llfirstuse.h"
-#include "llfoldertype.h"
-#include "llfloaterchat.h"
-#include "llfloatercustomize.h"
-#include "llfloaterproperties.h"
-#include "llfloaterworldmap.h"
-#include "llfocusmgr.h"
-#include "llfolderview.h"
-#include "llfriendcard.h"
-#include "llavataractions.h"
-#include "llgesturemgr.h"
-#include "lliconctrl.h"
-#include "llinventoryfunctions.h"
-#include "llinventorymodel.h"
-#include "llinventorypanel.h"
-#include "llinventoryclipboard.h"
-#include "lllineeditor.h"
-#include "llmenugl.h"
-#include "llpreviewanim.h"
-#include "llpreviewgesture.h"
-#include "llpreviewnotecard.h"
-#include "llpreviewscript.h"
-#include "llpreviewsound.h"
-#include "llpreviewtexture.h"
-#include "llresmgr.h"
-#include "llscrollcontainer.h"
-#include "llimview.h"
-#include "lltooldraganddrop.h"
-#include "llviewertexturelist.h"
-#include "llviewerinventory.h"
-#include "llviewerobjectlist.h"
-#include "llviewerwindow.h"
-#include "llvoavatar.h"
-#include "llwearable.h"
-#include "llwearablelist.h"
-#include "llviewermessage.h"
-#include "llviewerregion.h"
-#include "llvoavatarself.h"
-#include "lltabcontainer.h"
-#include "lluictrlfactory.h"
-#include "llselectmgr.h"
-#include "llsidetray.h"
-#include "llfloateropenobject.h"
-#include "lltrans.h"
-#include "llappearancemgr.h"
-
-using namespace LLOldEvents;
-
-// Helpers
-// bug in busy count inc/dec right now, logic is complex... do we really need it?
-void inc_busy_count()
-{
-// gViewerWindow->getWindow()->incBusyCount();
-// check balance of these calls if this code is changed to ever actually
-// *do* something!
-}
-void dec_busy_count()
-{
-// gViewerWindow->getWindow()->decBusyCount();
-// check balance of these calls if this code is changed to ever actually
-// *do* something!
-}
-
-// Function declarations
-void wear_add_inventory_item_on_avatar(LLInventoryItem* item);
-void remove_inventory_category_from_avatar(LLInventoryCategory* category);
-void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id);
-bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
-bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response);
-
-std::string ICON_NAME[ICON_NAME_COUNT] =
-{
- "Inv_Texture",
- "Inv_Sound",
- "Inv_CallingCard",
- "Inv_CallingCard",
- "Inv_Landmark",
- "Inv_Landmark",
- "Inv_Script",
- "Inv_Clothing",
- "Inv_Object",
- "Inv_Object",
- "Inv_Notecard",
- "Inv_Skin",
- "Inv_Snapshot",
-
- "Inv_BodyShape",
- "Inv_Skin",
- "Inv_Hair",
- "Inv_Eye",
- "Inv_Shirt",
- "Inv_Pants",
- "Inv_Shoe",
- "Inv_Socks",
- "Inv_Jacket",
- "Inv_Gloves",
- "Inv_Undershirt",
- "Inv_Underpants",
- "Inv_Skirt",
- "inv_item_alpha.tga",
- "inv_item_tattoo.tga",
-
- "Inv_Animation",
- "Inv_Gesture",
-
- "inv_item_linkitem.tga",
- "inv_item_linkfolder.tga"
-};
-
-
-// +=================================================+
-// | LLInventoryPanelObserver |
-// +=================================================+
-void LLInventoryPanelObserver::changed(U32 mask)
-{
- mIP->modelChanged(mask);
-}
-
-
-// +=================================================+
-// | LLInvFVBridge |
-// +=================================================+
-
-LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
-mUUID(uuid), mInvType(LLInventoryType::IT_NONE)
-{
- mInventoryPanel = inventory->getHandle();
-}
-
-const std::string& LLInvFVBridge::getName() const
-{
- LLInventoryObject* obj = getInventoryObject();
- if(obj)
- {
- return obj->getName();
- }
- return LLStringUtil::null;
-}
-
-const std::string& LLInvFVBridge::getDisplayName() const
-{
- return getName();
-}
-
-// Folders have full perms
-PermissionMask LLInvFVBridge::getPermissionMask() const
-{
-
- return PERM_ALL;
-}
-
-// virtual
-LLAssetType::EType LLInvFVBridge::getPreferredType() const
-{
- return LLAssetType::AT_NONE;
-}
-
-
-// Folders don't have creation dates.
-time_t LLInvFVBridge::getCreationDate() const
-{
- return 0;
-}
-
-// Can be destoryed (or moved to trash)
-BOOL LLInvFVBridge::isItemRemovable()
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
- {
- return TRUE;
- }
- return FALSE;
-}
-
-// Sends an update to all link items that point to the base item.
-void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string& new_name)
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
-
- LLInventoryItem* itemp = model->getItem(mUUID);
- if (!itemp) return;
-
- if (itemp->getIsLinkType())
- {
- return;
- }
-
- LLInventoryModel::item_array_t item_array = model->collectLinkedItems(item_id);
- for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
- iter != item_array.end();
- iter++)
- {
- LLViewerInventoryItem *linked_item = (*iter);
- if (linked_item->getUUID() == item_id) continue;
-
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item);
- new_item->rename(new_name);
- new_item->updateServer(FALSE);
- model->updateItem(new_item);
- // model->addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
- }
- model->notifyObservers();
-}
-
-// Can be moved to another folder
-BOOL LLInvFVBridge::isItemMovable() const
-{
- return TRUE;
-}
-
-/*virtual*/
-/**
- * @brief Adds this item into clipboard storage
- */
-void LLInvFVBridge::cutToClipboard()
-{
- if(isItemMovable())
- {
- LLInventoryClipboard::instance().cut(mUUID);
- }
-}
-// *TODO: make sure this does the right thing
-void LLInvFVBridge::showProperties()
-{
- LLSD key;
- key["id"] = mUUID;
- LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
-
- // LLFloaterReg::showInstance("properties", mUUID);
-}
-
-void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
-{
- // Deactivate gestures when moving them into Trash
- LLInvFVBridge* bridge;
- LLInventoryModel* model = getInventoryModel();
- LLViewerInventoryItem* item = NULL;
- LLViewerInventoryCategory* cat = NULL;
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- S32 count = batch.count();
- S32 i,j;
- for(i = 0; i < count; ++i)
- {
- bridge = (LLInvFVBridge*)(batch.get(i));
- if(!bridge || !bridge->isItemRemovable()) continue;
- item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
- if (item)
- {
- if(LLAssetType::AT_GESTURE == item->getType())
- {
- LLGestureManager::instance().deactivateGesture(item->getUUID());
- }
- }
- }
- for(i = 0; i < count; ++i)
- {
- bridge = (LLInvFVBridge*)(batch.get(i));
- if(!bridge || !bridge->isItemRemovable()) continue;
- cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
- if (cat)
- {
- gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE );
- for (j=0; j<descendent_items.count(); j++)
- {
- if(LLAssetType::AT_GESTURE == descendent_items[j]->getType())
- {
- LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID());
- }
- }
- }
- }
- removeBatchNoCheck(batch);
-}
-
-void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch)
-{
- // this method moves a bunch of items and folders to the trash. As
- // per design guidelines for the inventory model, the message is
- // built and the accounting is performed first. After all of that,
- // we call LLInventoryModel::moveObject() to move everything
- // around.
- LLInvFVBridge* bridge;
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLMessageSystem* msg = gMessageSystem;
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
- LLViewerInventoryItem* item = NULL;
- LLViewerInventoryCategory* cat = NULL;
- std::vector<LLUUID> move_ids;
- LLInventoryModel::update_map_t update;
- bool start_new_message = true;
- S32 count = batch.count();
- S32 i;
- for(i = 0; i < count; ++i)
- {
- bridge = (LLInvFVBridge*)(batch.get(i));
- if(!bridge || !bridge->isItemRemovable()) continue;
- item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
- if(item)
- {
- if(item->getParentUUID() == trash_id) continue;
- move_ids.push_back(item->getUUID());
- LLPreview::hide(item->getUUID());
- --update[item->getParentUUID()];
- ++update[trash_id];
- if(start_new_message)
- {
- start_new_message = false;
- msg->newMessageFast(_PREHASH_MoveInventoryItem);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addBOOLFast(_PREHASH_Stamp, TRUE);
- }
- msg->nextBlockFast(_PREHASH_InventoryData);
- msg->addUUIDFast(_PREHASH_ItemID, item->getUUID());
- msg->addUUIDFast(_PREHASH_FolderID, trash_id);
- msg->addString("NewName", NULL);
- if(msg->isSendFullFast(_PREHASH_InventoryData))
- {
- start_new_message = true;
- gAgent.sendReliableMessage();
- gInventory.accountForUpdate(update);
- update.clear();
- }
- }
- }
- if(!start_new_message)
- {
- start_new_message = true;
- gAgent.sendReliableMessage();
- gInventory.accountForUpdate(update);
- update.clear();
- }
- for(i = 0; i < count; ++i)
- {
- bridge = (LLInvFVBridge*)(batch.get(i));
- if(!bridge || !bridge->isItemRemovable()) continue;
- cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
- if(cat)
- {
- if(cat->getParentUUID() == trash_id) continue;
- move_ids.push_back(cat->getUUID());
- --update[cat->getParentUUID()];
- ++update[trash_id];
- if(start_new_message)
- {
- start_new_message = false;
- msg->newMessageFast(_PREHASH_MoveInventoryFolder);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addBOOL("Stamp", TRUE);
- }
- msg->nextBlockFast(_PREHASH_InventoryData);
- msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID());
- msg->addUUIDFast(_PREHASH_ParentID, trash_id);
- if(msg->isSendFullFast(_PREHASH_InventoryData))
- {
- start_new_message = true;
- gAgent.sendReliableMessage();
- gInventory.accountForUpdate(update);
- update.clear();
- }
- }
- }
- if(!start_new_message)
- {
- gAgent.sendReliableMessage();
- gInventory.accountForUpdate(update);
- }
-
- // move everything.
- std::vector<LLUUID>::iterator it = move_ids.begin();
- std::vector<LLUUID>::iterator end = move_ids.end();
- for(; it != end; ++it)
- {
- gInventory.moveObject((*it), trash_id);
- }
-
- // notify inventory observers.
- model->notifyObservers();
-}
-
-BOOL LLInvFVBridge::isClipboardPasteable() const
-{
- if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
- {
- return FALSE;
- }
- LLInventoryModel* model = getInventoryModel();
- if (!model)
- {
- return FALSE;
- }
-
- const LLUUID &agent_id = gAgent.getID();
-
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
- for(S32 i = 0; i < count; i++)
- {
- const LLUUID &item_id = objects.get(i);
-
- // Can't paste folders
- const LLInventoryCategory *cat = model->getCategory(item_id);
- if (cat)
- {
- return FALSE;
- }
-
- const LLInventoryItem *item = model->getItem(item_id);
- if (item)
- {
- if (!item->getPermissions().allowCopyBy(agent_id))
- {
- return FALSE;
- }
- }
- }
- return TRUE;
-}
-
-BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
-{
- if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
- {
- return FALSE;
- }
- const LLInventoryModel* model = getInventoryModel();
- if (!model)
- {
- return FALSE;
- }
-
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
- for(S32 i = 0; i < count; i++)
- {
- const LLInventoryItem *item = model->getItem(objects.get(i));
- if (item)
- {
- if (!LLAssetType::lookupCanLink(item->getActualType()))
- {
- return FALSE;
- }
- }
- const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i));
- if (cat && !LLAssetType::lookupCanLink(cat->getPreferredType()))
- {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-void hide_context_entries(LLMenuGL& menu,
- const std::vector<std::string> &entries_to_show,
- const std::vector<std::string> &disabled_entries)
-{
- const LLView::child_list_t *list = menu.getChildList();
-
- LLView::child_list_t::const_iterator itor;
- for (itor = list->begin(); itor != list->end(); ++itor)
- {
- std::string name = (*itor)->getName();
-
- // descend into split menus:
- LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor);
- if ((name == "More") && branchp)
- {
- hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries);
- }
-
-
- bool found = false;
- std::vector<std::string>::const_iterator itor2;
- for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
- {
- if (*itor2 == name)
- {
- found = true;
- }
- }
- if (!found)
- {
- (*itor)->setVisible(FALSE);
- }
- else
- {
- for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
- {
- if (*itor2 == name)
- {
- (*itor)->setEnabled(FALSE);
- }
- }
- }
- }
-}
-
-// Helper for commonly-used entries
-void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
- std::vector<std::string> &items,
- std::vector<std::string> &disabled_items, U32 flags)
-{
- items.push_back(std::string("Rename"));
- if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Rename"));
- }
-
- if (show_asset_id)
- {
- items.push_back(std::string("Copy Asset UUID"));
- if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
- || (flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Copy Asset UUID"));
- }
- }
-
- items.push_back(std::string("Copy Separator"));
-
- items.push_back(std::string("Copy"));
- if (!isItemCopyable())
- {
- disabled_items.push_back(std::string("Copy"));
- }
-
- items.push_back(std::string("Paste"));
- if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Paste"));
- }
-
- items.push_back(std::string("Paste As Link"));
- if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Paste As Link"));
- }
- items.push_back(std::string("Paste Separator"));
-
- items.push_back(std::string("Delete"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Delete"));
- }
-}
-
-void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
- {
- items.push_back(std::string("PurgeItem"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("PurgeItem"));
- }
- items.push_back(std::string("RestoreItem"));
- }
- else
- {
- items.push_back(std::string("Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-// *TODO: remove this
-BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
-{
- BOOL rv = FALSE;
-
- const LLInventoryObject* obj = getInventoryObject();
-
- if(obj)
- {
- *type = LLAssetType::lookupDragAndDropType(obj->getActualType());
- if(*type == DAD_NONE)
- {
- return FALSE;
- }
-
- *id = obj->getUUID();
- //object_ids.put(obj->getUUID());
-
- if (*type == DAD_CATEGORY)
- {
- gInventory.startBackgroundFetch(obj->getUUID());
- }
-
- rv = TRUE;
- }
-
- return rv;
-}
-
-LLInventoryObject* LLInvFVBridge::getInventoryObject() const
-{
- LLInventoryObject* obj = NULL;
- LLInventoryModel* model = getInventoryModel();
- if(model)
- {
- obj = (LLInventoryObject*)model->getObject(mUUID);
- }
- return obj;
-}
-
-LLInventoryModel* LLInvFVBridge::getInventoryModel() const
-{
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- return panel ? panel->getModel() : NULL;
-}
-
-BOOL LLInvFVBridge::isInTrash() const
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
- return model->isObjectDescendentOf(mUUID, trash_id);
-}
-
-BOOL LLInvFVBridge::isLinkedObjectInTrash() const
-{
- if (isInTrash()) return TRUE;
-
- const LLInventoryObject *obj = getInventoryObject();
- if (obj && obj->getIsLinkType())
- {
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
- return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id);
- }
- return FALSE;
-}
-
-BOOL LLInvFVBridge::isAgentInventory() const
-{
- const LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- if(gInventory.getRootFolderID() == mUUID) return TRUE;
- return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
-}
-
-BOOL LLInvFVBridge::isCOFFolder() const
-{
- const LLInventoryModel* model = getInventoryModel();
- if(!model) return TRUE;
- const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
- if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id))
- {
- return TRUE;
- }
- return FALSE;
-}
-
-BOOL LLInvFVBridge::isItemPermissive() const
-{
- return FALSE;
-}
-
-// static
-void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
- LLViewerInventoryItem* item,
- const LLUUID& new_parent,
- BOOL restamp)
-{
- if(item->getParentUUID() != new_parent)
- {
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
-
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
- new_item->setParent(new_parent);
- new_item->updateParentOnServer(restamp);
- model->updateItem(new_item);
- model->notifyObservers();
- }
-}
-
-// static
-void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
- LLViewerInventoryCategory* cat,
- const LLUUID& new_parent,
- BOOL restamp)
-{
- if(cat->getParentUUID() != new_parent)
- {
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
-
- LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
- new_cat->setParent(new_parent);
- new_cat->updateParentOnServer(restamp);
- model->updateCategory(new_cat);
- model->notifyObservers();
- }
-}
-
-
-const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type)
-{
- const std::string rv= LLInventoryType::lookup(inv_type);
- if(rv.empty())
- {
- return std::string("<invalid>");
- }
- return rv;
-}
-
-LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
- LLAssetType::EType actual_asset_type,
- LLInventoryType::EType inv_type,
- LLInventoryPanel* inventory,
- const LLUUID& uuid,
- U32 flags)
-{
- LLInvFVBridge* new_listener = NULL;
- switch(asset_type)
- {
- case LLAssetType::AT_TEXTURE:
- if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLTextureBridge(inventory, uuid, inv_type);
- break;
-
- case LLAssetType::AT_SOUND:
- if(!(inv_type == LLInventoryType::IT_SOUND))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLSoundBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_LANDMARK:
- if(!(inv_type == LLInventoryType::IT_LANDMARK))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLLandmarkBridge(inventory, uuid, flags);
- break;
-
- case LLAssetType::AT_CALLINGCARD:
- if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLCallingCardBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_SCRIPT:
- if(!(inv_type == LLInventoryType::IT_LSL))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLScriptBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_OBJECT:
- if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags);
- break;
-
- case LLAssetType::AT_NOTECARD:
- if(!(inv_type == LLInventoryType::IT_NOTECARD))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLNotecardBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_ANIMATION:
- if(!(inv_type == LLInventoryType::IT_ANIMATION))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLAnimationBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_GESTURE:
- if(!(inv_type == LLInventoryType::IT_GESTURE))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLGestureBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_LSL_TEXT:
- if(!(inv_type == LLInventoryType::IT_LSL))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLLSLTextBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_BODYPART:
- if(!(inv_type == LLInventoryType::IT_WEARABLE))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags);
- break;
- case LLAssetType::AT_CATEGORY:
- case LLAssetType::AT_ROOT_CATEGORY:
- if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
- {
- // Create a link folder handler instead.
- new_listener = new LLLinkFolderBridge(inventory, uuid);
- break;
- }
- new_listener = new LLFolderBridge(inventory, uuid);
- break;
- case LLAssetType::AT_LINK:
- // Only should happen for broken links.
- new_listener = new LLLinkItemBridge(inventory, uuid);
- break;
- case LLAssetType::AT_LINK_FOLDER:
- // Only should happen for broken links.
- new_listener = new LLLinkItemBridge(inventory, uuid);
- break;
- default:
- llinfos << "Unhandled asset type (llassetstorage.h): "
- << (S32)asset_type << llendl;
- break;
- }
-
- if (new_listener)
- {
- new_listener->mInvType = inv_type;
- }
-
- return new_listener;
-}
-
-void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
-{
- LLInventoryCategory* cat = model->getCategory(uuid);
- if (cat)
- {
- model->purgeDescendentsOf(uuid);
- model->notifyObservers();
- }
- LLInventoryObject* obj = model->getObject(uuid);
- if (obj)
- {
- model->purgeObject(uuid);
- model->notifyObservers();
- }
-}
-
-// +=================================================+
-// | InventoryFVBridgeBuilder |
-// +=================================================+
-LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type,
- LLAssetType::EType actual_asset_type,
- LLInventoryType::EType inv_type,
- LLInventoryPanel* inventory,
- const LLUUID& uuid,
- U32 flags /* = 0x00 */) const
-{
- return LLInvFVBridge::createBridge(asset_type,
- actual_asset_type,
- inv_type,
- inventory,
- uuid,
- flags);
-}
-
-// +=================================================+
-// | LLItemBridge |
-// +=================================================+
-
-void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("goto" == action)
- {
- gotoItem(folder);
- }
- if ("open" == action)
- {
- openItem();
- return;
- }
- else if ("properties" == action)
- {
- showProperties();
- return;
- }
- else if ("purge" == action)
- {
- purgeItem(model, mUUID);
- return;
- }
- else if ("restoreToWorld" == action)
- {
- restoreToWorld();
- return;
- }
- else if ("restore" == action)
- {
- restoreItem();
- return;
- }
- else if ("copy_uuid" == action)
- {
- // Single item only
- LLInventoryItem* item = model->getItem(mUUID);
- if(!item) return;
- LLUUID asset_id = item->getAssetUUID();
- std::string buffer;
- asset_id.toString(buffer);
-
- gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
- return;
- }
- else if ("copy" == action)
- {
- copyToClipboard();
- return;
- }
- else if ("paste" == action)
- {
- // Single item only
- LLInventoryItem* itemp = model->getItem(mUUID);
- if (!itemp) return;
-
- LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
- if (!folder_view_itemp) return;
-
- folder_view_itemp->getListener()->pasteFromClipboard();
- return;
- }
- else if ("paste_link" == action)
- {
- // Single item only
- LLInventoryItem* itemp = model->getItem(mUUID);
- if (!itemp) return;
-
- LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
- if (!folder_view_itemp) return;
-
- folder_view_itemp->getListener()->pasteLinkFromClipboard();
- return;
- }
-}
-
-void LLItemBridge::selectItem()
-{
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
- if(item && !item->isComplete())
- {
- item->fetchFromServer();
- }
-}
-
-void LLItemBridge::restoreItem()
-{
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
- if(item)
- {
- LLInventoryModel* model = getInventoryModel();
- const LLUUID new_parent = model->findCategoryUUIDForType(item->getType());
- // do not restamp on restore.
- LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);
- }
-}
-
-void LLItemBridge::restoreToWorld()
-{
- LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)getItem();
- if (itemp)
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessage("RezRestoreToWorld");
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-
- msg->nextBlockFast(_PREHASH_InventoryData);
- itemp->packMessage(msg);
- msg->sendReliable(gAgent.getRegion()->getHost());
- }
-
- //Similar functionality to the drag and drop rez logic
- BOOL remove_from_inventory = FALSE;
-
- //remove local inventory copy, sim will deal with permissions and removing the item
- //from the actual inventory if its a no-copy etc
- if(!itemp->getPermissions().allowCopyBy(gAgent.getID()))
- {
- remove_from_inventory = TRUE;
- }
-
- // Check if it's in the trash. (again similar to the normal rez logic)
- const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
- if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id))
- {
- remove_from_inventory = TRUE;
- }
-
- if(remove_from_inventory)
- {
- gInventory.deleteObject(itemp->getUUID());
- gInventory.notifyObservers();
- }
-}
-
-void LLItemBridge::gotoItem(LLFolderView *folder)
-{
- LLInventoryObject *obj = getInventoryObject();
- if (obj && obj->getIsLinkType())
- {
- LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
- if (active_panel)
- {
- active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO);
- }
- }
-}
-
-LLUIImagePtr LLItemBridge::getIcon() const
-{
- return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]);
-}
-
-PermissionMask LLItemBridge::getPermissionMask() const
-{
- LLViewerInventoryItem* item = getItem();
- PermissionMask perm_mask = 0;
- if(item)
- {
- BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
- BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
- BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
- gAgent.getID());
-
- if (copy) perm_mask |= PERM_COPY;
- if (mod) perm_mask |= PERM_MODIFY;
- if (xfer) perm_mask |= PERM_TRANSFER;
-
- }
- return perm_mask;
-}
-
-const std::string& LLItemBridge::getDisplayName() const
-{
- if(mDisplayName.empty())
- {
- buildDisplayName(getItem(), mDisplayName);
- }
- return mDisplayName;
-}
-
-void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
-{
- if(item)
- {
- name.assign(item->getName());
- }
- else
- {
- name.assign(LLStringUtil::null);
- }
-}
-
-LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
-{
- U8 font = LLFontGL::NORMAL;
-
- if( gAgentWearables.isWearingItem( mUUID ) )
- {
- // llinfos << "BOLD" << llendl;
- font |= LLFontGL::BOLD;
- }
-
- const LLViewerInventoryItem* item = getItem();
- if (item && item->getIsLinkType())
- {
- font |= LLFontGL::ITALIC;
- }
- return (LLFontGL::StyleFlags)font;
-}
-
-std::string LLItemBridge::getLabelSuffix() const
-{
- // String table is loaded before login screen and inventory items are
- // loaded after login, so LLTrans should be ready.
- static std::string NO_COPY =LLTrans::getString("no_copy");
- static std::string NO_MOD = LLTrans::getString("no_modify");
- static std::string NO_XFER = LLTrans::getString("no_transfer");
- static std::string LINK = LLTrans::getString("link");
- static std::string BROKEN_LINK = LLTrans::getString("broken_link");
- std::string suffix;
- LLInventoryItem* item = getItem();
- if(item)
- {
- // it's a bit confusing to put nocopy/nomod/etc on calling cards.
- if(LLAssetType::AT_CALLINGCARD != item->getType()
- && item->getPermissions().getOwner() == gAgent.getID())
- {
- BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType());
- if (broken_link) return BROKEN_LINK;
-
- BOOL link = item->getIsLinkType();
- if (link) return LINK;
-
- BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
- if (!copy)
- {
- suffix += NO_COPY;
- }
- BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
- if (!mod)
- {
- suffix += NO_MOD;
- }
- BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
- gAgent.getID());
- if (!xfer)
- {
- suffix += NO_XFER;
- }
- }
- }
- return suffix;
-}
-
-time_t LLItemBridge::getCreationDate() const
-{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- return item->getCreationDate();
- }
- return 0;
-}
-
-
-BOOL LLItemBridge::isItemRenameable() const
-{
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- // (For now) Don't allow calling card rename since that may confuse users as to
- // what the calling card points to.
- if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
- {
- return FALSE;
- }
- return (item->getPermissions().allowModifyBy(gAgent.getID()));
- }
- return FALSE;
-}
-
-BOOL LLItemBridge::renameItem(const std::string& new_name)
-{
- if(!isItemRenameable())
- return FALSE;
- LLPreview::dirty(mUUID);
- LLInventoryModel* model = getInventoryModel();
- if(!model)
- return FALSE;
- LLViewerInventoryItem* item = getItem();
- if(item && (item->getName() != new_name))
- {
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
- new_item->rename(new_name);
- buildDisplayName(new_item, mDisplayName);
- new_item->updateServer(FALSE);
- model->updateItem(new_item);
-
- model->notifyObservers();
- }
- // return FALSE because we either notified observers (& therefore
- // rebuilt) or we didn't update.
- return FALSE;
-}
-
-
-BOOL LLItemBridge::removeItem()
-{
- if(!isItemRemovable())
- {
- return FALSE;
- }
- // move it to the trash
- LLPreview::hide(mUUID, TRUE);
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
- LLViewerInventoryItem* item = getItem();
-
- // if item is not already in trash
- if(item && !model->isObjectDescendentOf(mUUID, trash_id))
- {
- // move to trash, and restamp
- LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE);
- // delete was successful
- return TRUE;
- }
- else
- {
- // tried to delete already item in trash (should purge?)
- return FALSE;
- }
-}
-
-BOOL LLItemBridge::isItemCopyable() const
-{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- // can't copy worn objects. DEV-15183
- LLVOAvatarSelf *avatarp = gAgent.getAvatarObject();
- if( !avatarp )
- {
- return FALSE;
- }
-
- if(avatarp->isWearingAttachment(mUUID))
- {
- return FALSE;
- }
-
- // All items can be copied, not all can be pasted.
- // The only time an item can't be copied is if it's a link
- // return (item->getPermissions().allowCopyBy(gAgent.getID()));
- if (item->getIsLinkType())
- {
- return FALSE;
- }
- return TRUE;
- }
- return FALSE;
-}
-BOOL LLItemBridge::copyToClipboard() const
-{
- if(isItemCopyable())
- {
- LLInventoryClipboard::instance().add(mUUID);
- return TRUE;
- }
- return FALSE;
-}
-
-LLViewerInventoryItem* LLItemBridge::getItem() const
-{
- LLViewerInventoryItem* item = NULL;
- LLInventoryModel* model = getInventoryModel();
- if(model)
- {
- item = (LLViewerInventoryItem*)model->getItem(mUUID);
- }
- return item;
-}
-
-BOOL LLItemBridge::isItemPermissive() const
-{
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- U32 mask = item->getPermissions().getMaskBase();
- if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
- {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-// +=================================================+
-// | LLFolderBridge |
-// +=================================================+
-
-LLFolderBridge* LLFolderBridge::sSelf=NULL;
-
-// Can be moved to another folder
-BOOL LLFolderBridge::isItemMovable() const
-{
- LLInventoryObject* obj = getInventoryObject();
- if(obj)
- {
- return (!LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)obj)->getPreferredType()));
- }
- return FALSE;
-}
-
-void LLFolderBridge::selectItem()
-{
-}
-
-
-// Can be destroyed (or moved to trash)
-BOOL LLFolderBridge::isItemRemovable()
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model)
- {
- return FALSE;
- }
-
- if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
- {
- return FALSE;
- }
-
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if( !avatar )
- {
- return FALSE;
- }
-
- LLInventoryCategory* category = model->getCategory(mUUID);
- if( !category )
- {
- return FALSE;
- }
-
- if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
- {
- return FALSE;
- }
-
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
-
- S32 i;
- for( i = 0; i < descendent_categories.count(); i++ )
- {
- LLInventoryCategory* category = descendent_categories[i];
- if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
- {
- return FALSE;
- }
- }
-
- for( i = 0; i < descendent_items.count(); i++ )
- {
- LLInventoryItem* item = descendent_items[i];
- if( (item->getType() == LLAssetType::AT_CLOTHING) ||
- (item->getType() == LLAssetType::AT_BODYPART) )
- {
- if(gAgentWearables.isWearingItem(item->getUUID()))
- {
- return FALSE;
- }
- }
- else
- if( item->getType() == LLAssetType::AT_OBJECT )
- {
- if(avatar->isWearingAttachment(item->getUUID()))
- {
- return FALSE;
- }
- }
- }
-
- return TRUE;
-}
-
-BOOL LLFolderBridge::isUpToDate() const
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
- if( !category )
- {
- return FALSE;
- }
-
- return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN;
-}
-
-BOOL LLFolderBridge::isItemCopyable() const
-{
- return TRUE;
-}
-
-BOOL LLFolderBridge::copyToClipboard() const
-{
- if(isItemCopyable())
- {
- LLInventoryClipboard::instance().add(mUUID);
- return TRUE;
- }
- return FALSE;
-}
-
-BOOL LLFolderBridge::isClipboardPasteable() const
-{
- if ( ! LLInvFVBridge::isClipboardPasteable() )
- return FALSE;
-
- // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
- if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) )
- {
- LLInventoryModel* model = getInventoryModel();
- if ( !model )
- {
- return FALSE;
- }
-
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- const LLViewerInventoryCategory *current_cat = getCategory();
-
- // Search for the direct descendent of current Friends subfolder among all pasted items,
- // and return false if is found.
- for(S32 i = objects.count() - 1; i >= 0; --i)
- {
- const LLUUID &obj_id = objects.get(i);
- if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
- {
- return FALSE;
- }
- }
-
- }
- return TRUE;
-}
-
-BOOL LLFolderBridge::isClipboardPasteableAsLink() const
-{
- // Check normal paste-as-link permissions
- if (!LLInvFVBridge::isClipboardPasteableAsLink())
- {
- return FALSE;
- }
-
- const LLInventoryModel* model = getInventoryModel();
- if (!model)
- {
- return FALSE;
- }
-
- const LLViewerInventoryCategory *current_cat = getCategory();
- if (current_cat)
- {
- const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat );
- const LLUUID ¤t_cat_id = current_cat->getUUID();
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
- for(S32 i = 0; i < count; i++)
- {
- const LLUUID &obj_id = objects.get(i);
- const LLInventoryCategory *cat = model->getCategory(obj_id);
- if (cat)
- {
- const LLUUID &cat_id = cat->getUUID();
- // Don't allow recursive pasting
- if ((cat_id == current_cat_id) ||
- model->isObjectDescendentOf(current_cat_id, cat_id))
- {
- return FALSE;
- }
- }
- // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
- if ( is_in_friend_folder )
- {
- // If object is direct descendent of current Friends subfolder than return false.
- // Note: We can't use 'const LLInventoryCategory *cat', because it may be null
- // in case type of obj_id is LLInventoryItem.
- if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
- {
- return FALSE;
- }
- }
- }
- }
- return TRUE;
-
-}
-
-BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
- BOOL drop)
-{
- // This should never happen, but if an inventory item is incorrectly parented,
- // the UI will get confused and pass in a NULL.
- if(!inv_cat) return FALSE;
-
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
-
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if(!avatar) return FALSE;
-
- // cannot drag categories into library
- if(!isAgentInventory())
- {
- return FALSE;
- }
-
- // check to make sure source is agent inventory, and is represented there.
- LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
- BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL)
- && (LLToolDragAndDrop::SOURCE_AGENT == source);
-
- BOOL accept = FALSE;
- S32 i;
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- if(is_agent_inventory)
- {
- const LLUUID& cat_id = inv_cat->getUUID();
-
- // Is the destination the trash?
- const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
- BOOL move_is_into_trash = (mUUID == trash_id)
- || model->isObjectDescendentOf(mUUID, trash_id);
- BOOL is_movable = (!LLAssetType::lookupIsProtectedCategoryType(inv_cat->getPreferredType()));
- LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
- BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
- BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT);
- if (move_is_into_current_outfit || move_is_into_outfit)
- {
- // BAP - restrictions?
- is_movable = true;
- }
-
- if (mUUID == gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE))
- {
- is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604
- }
-
- if( is_movable )
- {
- gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE );
-
- for( i = 0; i < descendent_categories.count(); i++ )
- {
- LLInventoryCategory* category = descendent_categories[i];
- if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
- {
- // ...can't move "special folders" like Textures
- is_movable = FALSE;
- break;
- }
- }
-
- if( is_movable )
- {
- if( move_is_into_trash )
- {
- for( i = 0; i < descendent_items.count(); i++ )
- {
- LLInventoryItem* item = descendent_items[i];
- if( (item->getType() == LLAssetType::AT_CLOTHING) ||
- (item->getType() == LLAssetType::AT_BODYPART) )
- {
- if( gAgentWearables.isWearingItem( item->getUUID() ) )
- {
- is_movable = FALSE; // It's generally movable, but not into the trash!
- break;
- }
- }
- else
- if( item->getType() == LLAssetType::AT_OBJECT )
- {
- if( avatar->isWearingAttachment( item->getUUID() ) )
- {
- is_movable = FALSE; // It's generally movable, but not into the trash!
- break;
- }
- }
- }
- }
- }
- }
-
-
- accept = is_movable
- && (mUUID != cat_id) // Can't move a folder into itself
- && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing
- && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity
- if(accept && drop)
- {
- // Look for any gestures and deactivate them
- if (move_is_into_trash)
- {
- for (i = 0; i < descendent_items.count(); i++)
- {
- LLInventoryItem* item = descendent_items[i];
- if (item->getType() == LLAssetType::AT_GESTURE
- && LLGestureManager::instance().isGestureActive(item->getUUID()))
- {
- LLGestureManager::instance().deactivateGesture(item->getUUID());
- }
- }
- }
- // if target is an outfit or current outfit folder we use link
- if (move_is_into_current_outfit || move_is_into_outfit)
- {
-#if SUPPORT_ENSEMBLES
- // BAP - should skip if dup.
- if (move_is_into_current_outfit)
- {
- LLAppearanceManager::wearEnsemble(inv_cat);
- }
- else
- {
- LLPointer<LLInventoryCallback> cb = NULL;
- link_inventory_item(
- gAgent.getID(),
- inv_cat->getUUID(),
- mUUID,
- inv_cat->getName(),
- LLAssetType::AT_LINK_FOLDER,
- cb);
- }
-#endif
- }
- else
- {
-
- // Reparent the folder and restamp children if it's moving
- // into trash.
- LLInvFVBridge::changeCategoryParent(
- model,
- (LLViewerInventoryCategory*)inv_cat,
- mUUID,
- move_is_into_trash);
- }
- }
- }
- else if(LLToolDragAndDrop::SOURCE_WORLD == source)
- {
- // content category has same ID as object itself
- LLUUID object_id = inv_cat->getUUID();
- LLUUID category_id = mUUID;
- accept = move_inv_category_world_to_agent(object_id, category_id, drop);
- }
- return accept;
-}
-
-void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv)
-{
- const char* dialog = NULL;
- if (object->flagScripted())
- {
- dialog = "MoveInventoryFromScriptedObject";
- }
- else
- {
- dialog = "MoveInventoryFromObject";
- }
- LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv));
-}
-
-// Move/copy all inventory items from the Contents folder of an in-world
-// object to the agent's inventory, inside a given category.
-BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
- const LLUUID& category_id,
- BOOL drop,
- void (*callback)(S32, void*),
- void* user_data)
-{
- // Make sure the object exists. If we allowed dragging from
- // anonymous objects, it would be possible to bypass
- // permissions.
- // content category has same ID as object itself
- LLViewerObject* object = gObjectList.findObject(object_id);
- if(!object)
- {
- llinfos << "Object not found for drop." << llendl;
- return FALSE;
- }
-
- // this folder is coming from an object, as there is only one folder in an object, the root,
- // we need to collect the entire contents and handle them as a group
- InventoryObjectList inventory_objects;
- object->getInventoryContents(inventory_objects);
-
- if (inventory_objects.empty())
- {
- llinfos << "Object contents not found for drop." << llendl;
- return FALSE;
- }
-
- BOOL accept = TRUE;
- BOOL is_move = FALSE;
-
- // coming from a task. Need to figure out if the person can
- // move/copy this item.
- InventoryObjectList::iterator it = inventory_objects.begin();
- InventoryObjectList::iterator end = inventory_objects.end();
- for ( ; it != end; ++it)
- {
- // coming from a task. Need to figure out if the person can
- // move/copy this item.
- LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions());
- if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
- && perm.allowTransferTo(gAgent.getID())))
-// || gAgent.isGodlike())
- {
- accept = TRUE;
- }
- else if(object->permYouOwner())
- {
- // If the object cannot be copied, but the object the
- // inventory is owned by the agent, then the item can be
- // moved from the task to agent inventory.
- is_move = TRUE;
- accept = TRUE;
- }
- else
- {
- accept = FALSE;
- break;
- }
- }
-
- if(drop && accept)
- {
- it = inventory_objects.begin();
- InventoryObjectList::iterator first_it = inventory_objects.begin();
- LLMoveInv* move_inv = new LLMoveInv;
- move_inv->mObjectID = object_id;
- move_inv->mCategoryID = category_id;
- move_inv->mCallback = callback;
- move_inv->mUserData = user_data;
-
- for ( ; it != end; ++it)
- {
- two_uuids_t two(category_id, (*it)->getUUID());
- move_inv->mMoveList.push_back(two);
- }
-
- if(is_move)
- {
- // Callback called from within here.
- warn_move_inventory(object, move_inv);
- }
- else
- {
- LLNotification::Params params("MoveInventoryFromObject");
- params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
- LLNotifications::instance().forceResponse(params, 0);
- }
- }
- return accept;
-}
-
-bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
-{
- // Valid COF items are:
- // - links to wearables (body parts or clothing)
- // - links to attachments
- // - links to gestures
- // - links to ensemble folders
- LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); // BAP - safe?
- if (linked_item)
- {
- LLAssetType::EType type = linked_item->getType();
- return (type == LLAssetType::AT_CLOTHING ||
- type == LLAssetType::AT_BODYPART ||
- type == LLAssetType::AT_GESTURE ||
- type == LLAssetType::AT_OBJECT);
- }
- else
- {
- LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe?
- // BAP remove AT_NONE support after ensembles are fully working?
- return (linked_category &&
- ((linked_category->getPreferredType() == LLAssetType::AT_NONE) ||
- (LLAssetType::lookupIsEnsembleCategoryType(linked_category->getPreferredType()))));
- }
-}
-
-
-bool LLFindWearables::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
-{
- if(item)
- {
- if((item->getType() == LLAssetType::AT_CLOTHING)
- || (item->getType() == LLAssetType::AT_BODYPART))
- {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-
-
-//Used by LLFolderBridge as callback for directory recursion.
-class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
-{
-public:
- LLRightClickInventoryFetchObserver() :
- mCopyItems(false)
- { };
- LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) :
- mCatID(cat_id),
- mCopyItems(copy_items)
- { };
- virtual void done()
- {
- // we've downloaded all the items, so repaint the dialog
- LLFolderBridge::staticFolderOptionsMenu();
-
- gInventory.removeObserver(this);
- delete this;
- }
-
-
-protected:
- LLUUID mCatID;
- bool mCopyItems;
-
-};
-
-//Used by LLFolderBridge as callback for directory recursion.
-class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
-{
-public:
- LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {}
- ~LLRightClickInventoryFetchDescendentsObserver() {}
- virtual void done();
-protected:
- bool mCopyItems;
-};
-
-void LLRightClickInventoryFetchDescendentsObserver::done()
-{
- // Avoid passing a NULL-ref as mCompleteFolders.front() down to
- // gInventory.collectDescendents()
- if( mCompleteFolders.empty() )
- {
- llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl;
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
- return;
- }
-
- // What we do here is get the complete information on the items in
- // the library, and set up an observer that will wait for that to
- // happen.
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- gInventory.collectDescendents(mCompleteFolders.front(),
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH);
- S32 count = item_array.count();
-#if 0 // HACK/TODO: Why?
- // This early causes a giant menu to get produced, and doesn't seem to be needed.
- if(!count)
- {
- llwarns << "Nothing fetched in category " << mCompleteFolders.front()
- << llendl;
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
- return;
- }
-#endif
-
- LLRightClickInventoryFetchObserver* outfit;
- outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems);
- LLInventoryFetchObserver::item_ref_t ids;
- for(S32 i = 0; i < count; ++i)
- {
- ids.push_back(item_array.get(i)->getUUID());
- }
-
- // clean up, and remove this as an observer since the call to the
- // outfit could notify observers and throw us into an infinite
- // loop.
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
-
- // increment busy count and either tell the inventory to check &
- // call done, or add this object to the inventory for observation.
- inc_busy_count();
-
- // do the fetch
- outfit->fetchItems(ids);
- outfit->done(); //Not interested in waiting and this will be right 99% of the time.
-//Uncomment the following code for laggy Inventory UI.
-/* if(outfit->isEverythingComplete())
- {
- // everything is already here - call done.
- outfit->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(outfit);
- }*/
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryWearObserver
-//
-// Observer for "copy and wear" operation to support knowing
-// when the all of the contents have been added to inventory.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryCopyAndWearObserver : public LLInventoryObserver
-{
-public:
- LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {}
- virtual ~LLInventoryCopyAndWearObserver() {}
- virtual void changed(U32 mask);
-
-protected:
- LLUUID mCatID;
- int mContentsCount;
- BOOL mFolderAdded;
-};
-
-
-
-void LLInventoryCopyAndWearObserver::changed(U32 mask)
-{
- if((mask & (LLInventoryObserver::ADD)) != 0)
- {
- if (!mFolderAdded)
- {
- const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
-
- std::set<LLUUID>::const_iterator id_it = changed_items.begin();
- std::set<LLUUID>::const_iterator id_end = changed_items.end();
- for (;id_it != id_end; ++id_it)
- {
- if ((*id_it) == mCatID)
- {
- mFolderAdded = TRUE;
- break;
- }
- }
- }
-
- if (mFolderAdded)
- {
- LLViewerInventoryCategory* category = gInventory.getCategory(mCatID);
-
- if (NULL == category)
- {
- llwarns << "gInventory.getCategory(" << mCatID
- << ") was NULL" << llendl;
- }
- else
- {
- if (category->getDescendentCount() ==
- mContentsCount)
- {
- gInventory.removeObserver(this);
- LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE);
- delete this;
- }
- }
- }
-
- }
-}
-
-
-
-void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("open" == action)
- {
- openItem();
- return;
- }
- else if ("paste" == action)
- {
- pasteFromClipboard();
- return;
- }
- else if ("paste_link" == action)
- {
- pasteLinkFromClipboard();
- return;
- }
- else if ("properties" == action)
- {
- showProperties();
- return;
- }
- else if ("replaceoutfit" == action)
- {
- modifyOutfit(FALSE);
- return;
- }
-#if SUPPORT_ENSEMBLES
- else if ("wearasensemble" == action)
- {
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLViewerInventoryCategory* cat = getCategory();
- if(!cat) return;
- LLAppearanceManager::wearEnsemble(cat,true);
- return;
- }
-#endif
- else if ("addtooutfit" == action)
- {
- modifyOutfit(TRUE);
- return;
- }
- else if ("copy" == action)
- {
- copyToClipboard();
- return;
- }
- else if ("removefromoutfit" == action)
- {
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLViewerInventoryCategory* cat = getCategory();
- if(!cat) return;
-
- remove_inventory_category_from_avatar ( cat );
- return;
- }
- else if ("purge" == action)
- {
- purgeItem(model, mUUID);
- return;
- }
- else if ("restore" == action)
- {
- restoreItem();
- return;
- }
-}
-
-void LLFolderBridge::openItem()
-{
- lldebugs << "LLFolderBridge::openItem()" << llendl;
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- bool fetching_inventory = model->fetchDescendentsOf(mUUID);
- // Only change folder type if we have the folder contents.
- if (!fetching_inventory)
- {
- // Disabling this for now, it's causing crash when new items are added to folders
- // since folder type may change before new item item has finished processing.
- // determineFolderType();
- }
-}
-
-void LLFolderBridge::closeItem()
-{
- determineFolderType();
-}
-
-void LLFolderBridge::determineFolderType()
-{
- if (isUpToDate())
- {
- LLInventoryModel* model = getInventoryModel();
- LLViewerInventoryCategory* category = model->getCategory(mUUID);
- category->determineFolderType();
- }
-}
-
-BOOL LLFolderBridge::isItemRenameable() const
-{
- LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
- if(cat && !LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())
- && (cat->getOwnerID() == gAgent.getID()))
- {
- return TRUE;
- }
- return FALSE;
-}
-
-void LLFolderBridge::restoreItem()
-{
- LLViewerInventoryCategory* cat;
- cat = (LLViewerInventoryCategory*)getCategory();
- if(cat)
- {
- LLInventoryModel* model = getInventoryModel();
- LLUUID new_parent = model->findCategoryUUIDForType(cat->getType());
- // do not restamp children on restore
- LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE);
- }
-}
-
-LLAssetType::EType LLFolderBridge::getPreferredType() const
-{
- LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
- LLViewerInventoryCategory* cat = getCategory();
- if(cat)
- {
- preferred_type = cat->getPreferredType();
- }
-
- return preferred_type;
-}
-
-// Icons for folders are based on the preferred type
-LLUIImagePtr LLFolderBridge::getIcon() const
-{
- LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
- LLViewerInventoryCategory* cat = getCategory();
- if(cat)
- {
- preferred_type = cat->getPreferredType();
- }
- return getIcon(preferred_type);
-}
-
-LLUIImagePtr LLFolderBridge::getIcon(LLAssetType::EType preferred_type)
-{
- // we only have one folder image now
- return LLUI::getUIImage("Inv_FolderClosed");
-}
-
-BOOL LLFolderBridge::renameItem(const std::string& new_name)
-{
- if(!isItemRenameable())
- return FALSE;
- LLInventoryModel* model = getInventoryModel();
- if(!model)
- return FALSE;
- LLViewerInventoryCategory* cat = getCategory();
- if(cat && (cat->getName() != new_name))
- {
- LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
- new_cat->rename(new_name);
- new_cat->updateServer(FALSE);
- model->updateCategory(new_cat);
-
- model->notifyObservers();
- }
- // return FALSE because we either notified observers (& therefore
- // rebuilt) or we didn't update.
- return FALSE;
-}
-
-BOOL LLFolderBridge::removeItem()
-{
- if(!isItemRemovable())
- {
- return FALSE;
- }
- // move it to the trash
- LLPreview::hide(mUUID);
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
-
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
-
- // Look for any gestures and deactivate them
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
-
- S32 i;
- for (i = 0; i < descendent_items.count(); i++)
- {
- LLInventoryItem* item = descendent_items[i];
- if (item->getType() == LLAssetType::AT_GESTURE
- && LLGestureManager::instance().isGestureActive(item->getUUID()))
- {
- LLGestureManager::instance().deactivateGesture(item->getUUID());
- }
- }
-
- // go ahead and do the normal remove if no 'last calling
- // cards' are being removed.
- LLViewerInventoryCategory* cat = getCategory();
- if(cat)
- {
- LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE);
- }
-
- return TRUE;
-}
-
-void LLFolderBridge::pasteFromClipboard()
-{
- LLInventoryModel* model = getInventoryModel();
- if(model && isClipboardPasteable())
- {
- LLInventoryItem* item = NULL;
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
- const LLUUID parent_id(mUUID);
- for(S32 i = 0; i < count; i++)
- {
- item = model->getItem(objects.get(i));
- if (item)
- {
- if(LLInventoryClipboard::instance().isCutMode())
- {
- // move_inventory_item() is not enough,
- //we have to update inventory locally too
- changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE);
- }
- else
- {
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- parent_id,
- std::string(),
- LLPointer<LLInventoryCallback>(NULL));
- }
- }
- }
- }
-}
-
-void LLFolderBridge::pasteLinkFromClipboard()
-{
- const LLInventoryModel* model = getInventoryModel();
- if(model)
- {
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
- LLUUID parent_id(mUUID);
- for(S32 i = 0; i < count; i++)
- {
- const LLUUID &object_id = objects.get(i);
-#if SUPPORT_ENSEMBLES
- if (LLInventoryCategory *cat = model->getCategory(object_id))
- {
- link_inventory_item(
- gAgent.getID(),
- cat->getUUID(),
- parent_id,
- cat->getName(),
- LLAssetType::AT_LINK_FOLDER,
- LLPointer<LLInventoryCallback>(NULL));
- }
- else
-#endif
- if (LLInventoryItem *item = model->getItem(object_id))
- {
- link_inventory_item(
- gAgent.getID(),
- item->getUUID(),
- parent_id,
- item->getName(),
- LLAssetType::AT_LINK,
- LLPointer<LLInventoryCallback>(NULL));
- }
- }
- }
-}
-
-void LLFolderBridge::staticFolderOptionsMenu()
-{
- if (!sSelf) return;
- sSelf->folderOptionsMenu();
-}
-
-void LLFolderBridge::folderOptionsMenu()
-{
- std::vector<std::string> disabled_items;
-
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
-
- const LLInventoryCategory* category = model->getCategory(mUUID);
- LLAssetType::EType type = category->getPreferredType();
- const bool is_default_folder = category && LLAssetType::lookupIsProtectedCategoryType(type);
- // BAP change once we're no longer treating regular categories as ensembles.
- const bool is_ensemble = category && (type == LLAssetType::AT_NONE ||
- LLAssetType::lookupIsEnsembleCategoryType(type));
-
- // calling card related functionality for folders.
-
- // Only enable calling-card related options for non-default folders.
- if (!is_default_folder)
- {
- LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
- if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
- {
- mItems.push_back(std::string("Calling Card Separator"));
- mItems.push_back(std::string("Conference Chat Folder"));
- mItems.push_back(std::string("IM All Contacts In Folder"));
- }
- }
-
- // wearables related functionality for folders.
- //is_wearable
- LLFindWearables is_wearable;
- LLIsType is_object( LLAssetType::AT_OBJECT );
- LLIsType is_gesture( LLAssetType::AT_GESTURE );
-
- if (mWearables ||
- checkFolderForContentsOfType(model, is_wearable) ||
- checkFolderForContentsOfType(model, is_object) ||
- checkFolderForContentsOfType(model, is_gesture) )
- {
- mItems.push_back(std::string("Folder Wearables Separator"));
-
- // Only enable add/replace outfit for non-default folders.
- if (!is_default_folder)
- {
- mItems.push_back(std::string("Add To Outfit"));
- mItems.push_back(std::string("Replace Outfit"));
- }
- if (is_ensemble)
- {
- mItems.push_back(std::string("Wear As Ensemble"));
- }
- mItems.push_back(std::string("Take Off Items"));
- }
- hide_context_entries(*mMenu, mItems, disabled_items);
-}
-
-BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
-{
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- model->collectDescendentsIf(mUUID,
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_type);
- return ((item_array.count() > 0) ? TRUE : FALSE );
-}
-
-// Flags unused
-void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- mItems.clear();
- mDisabledItems.clear();
-
- lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
-// std::vector<std::string> disabled_items;
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
- LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
-
- mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point)
- mDisabledItems.clear(); //adding code to clear out disabled members from previous
- if (lost_and_found_id == mUUID)
- {
- // This is the lost+found folder.
- mItems.push_back(std::string("Empty Lost And Found"));
- }
-
- if(trash_id == mUUID)
- {
- // This is the trash.
- mItems.push_back(std::string("Empty Trash"));
- }
- else if(model->isObjectDescendentOf(mUUID, trash_id))
- {
- // This is a folder in the trash.
- mItems.clear(); // clear any items that used to exist
- mItems.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- mDisabledItems.push_back(std::string("Purge Item"));
- }
-
- mItems.push_back(std::string("Restore Item"));
- }
- else if(isAgentInventory()) // do not allow creating in library
- {
- LLViewerInventoryCategory *cat = getCategory();
-
- // BAP removed protected check to re-enable standard ops in untyped folders.
- // Not sure what the right thing is to do here.
- if (!isCOFFolder() && cat /*&&
- LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/)
- {
- // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
- if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
- mItems.push_back(std::string("New Folder"));
- mItems.push_back(std::string("New Script"));
- mItems.push_back(std::string("New Note"));
- mItems.push_back(std::string("New Gesture"));
- mItems.push_back(std::string("New Clothes"));
- mItems.push_back(std::string("New Body Parts"));
- mItems.push_back(std::string("Change Type"));
-
- LLViewerInventoryCategory *cat = getCategory();
- if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
- {
- mDisabledItems.push_back(std::string("Change Type"));
- }
-
- getClipboardEntries(false, mItems, mDisabledItems, flags);
- }
- else
- {
- // Want some but not all of the items from getClipboardEntries for outfits.
- if (cat && cat->getPreferredType()==LLAssetType::AT_OUTFIT)
- {
- mItems.push_back(std::string("Rename"));
- mItems.push_back(std::string("Delete"));
- }
- }
-
- //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
- mCallingCards = mWearables = FALSE;
-
- LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
- if (checkFolderForContentsOfType(model, is_callingcard))
- {
- mCallingCards=TRUE;
- }
-
- LLFindWearables is_wearable;
- LLIsType is_object( LLAssetType::AT_OBJECT );
- LLIsType is_gesture( LLAssetType::AT_GESTURE );
-
- if (checkFolderForContentsOfType(model, is_wearable) ||
- checkFolderForContentsOfType(model, is_object) ||
- checkFolderForContentsOfType(model, is_gesture) )
- {
- mWearables=TRUE;
- }
-
- mMenu = &menu;
- sSelf = this;
- LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
-
- LLInventoryFetchDescendentsObserver::folder_ref_t folders;
- LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
- if (category)
- {
- folders.push_back(category->getUUID());
- }
- fetch->fetchDescendents(folders);
- inc_busy_count();
- if(fetch->isEverythingComplete())
- {
- // everything is already here - call done.
- fetch->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(fetch);
- }
- }
- else
- {
- mItems.push_back(std::string("--no options--"));
- mDisabledItems.push_back(std::string("--no options--"));
- }
- hide_context_entries(menu, mItems, mDisabledItems);
-}
-
-BOOL LLFolderBridge::hasChildren() const
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- LLInventoryModel::EHasChildren has_children;
- has_children = gInventory.categoryHasChildren(mUUID);
- return has_children != LLInventoryModel::CHILDREN_NO;
-}
-
-BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data)
-{
- //llinfos << "LLFolderBridge::dragOrDrop()" << llendl;
- BOOL accept = FALSE;
- switch(cargo_type)
- {
- case DAD_TEXTURE:
- case DAD_SOUND:
- case DAD_CALLINGCARD:
- case DAD_LANDMARK:
- case DAD_SCRIPT:
- case DAD_OBJECT:
- case DAD_NOTECARD:
- case DAD_CLOTHING:
- case DAD_BODYPART:
- case DAD_ANIMATION:
- case DAD_GESTURE:
- case DAD_LINK:
- accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
- drop);
- break;
- case DAD_CATEGORY:
- if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID))
- {
- accept = FALSE;
- }
- else
- {
- accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop);
- }
- break;
- default:
- break;
- }
- return accept;
-}
-
-LLViewerInventoryCategory* LLFolderBridge::getCategory() const
-{
- LLViewerInventoryCategory* cat = NULL;
- LLInventoryModel* model = getInventoryModel();
- if(model)
- {
- cat = (LLViewerInventoryCategory*)model->getCategory(mUUID);
- }
- return cat;
-}
-
-
-// static
-void LLFolderBridge::pasteClipboard(void* user_data)
-{
- LLFolderBridge* self = (LLFolderBridge*)user_data;
- if(self) self->pasteFromClipboard();
-}
-
-void LLFolderBridge::createNewCategory(void* user_data)
-{
- LLFolderBridge* bridge = (LLFolderBridge*)user_data;
- if(!bridge) return;
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get());
- if (!panel) return;
- LLInventoryModel* model = panel->getModel();
- if(!model) return;
- LLUUID id;
- id = model->createNewCategory(bridge->getUUID(),
- LLAssetType::AT_NONE,
- LLStringUtil::null);
- model->notifyObservers();
-
- // At this point, the bridge has probably been deleted, but the
- // view is still there.
- panel->setSelection(id, TAKE_FOCUS_YES);
-}
-
-void LLFolderBridge::createNewShirt(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHIRT);
-}
-
-void LLFolderBridge::createNewPants(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PANTS);
-}
-
-void LLFolderBridge::createNewShoes(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHOES);
-}
-
-void LLFolderBridge::createNewSocks(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SOCKS);
-}
-
-void LLFolderBridge::createNewJacket(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_JACKET);
-}
-
-void LLFolderBridge::createNewSkirt(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIRT);
-}
-
-void LLFolderBridge::createNewGloves(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_GLOVES);
-}
-
-void LLFolderBridge::createNewUndershirt(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERSHIRT);
-}
-
-void LLFolderBridge::createNewUnderpants(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS);
-}
-
-void LLFolderBridge::createNewShape(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE);
-}
-
-void LLFolderBridge::createNewSkin(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIN);
-}
-
-void LLFolderBridge::createNewHair(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_HAIR);
-}
-
-void LLFolderBridge::createNewEyes(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES);
-}
-
-// static
-void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type)
-{
- if(!bridge) return;
- LLUUID parent_id = bridge->getUUID();
- createWearable(parent_id, type);
-}
-
-// Separate function so can be called by global menu as well as right-click
-// menu.
-// static
-void LLFolderBridge::createWearable(LLUUID parent_id, EWearableType type)
-{
- LLWearable* wearable = LLWearableList::instance().createNewWearable(type);
- LLAssetType::EType asset_type = wearable->getAssetType();
- LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
- create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
- parent_id, wearable->getTransactionID(), wearable->getName(),
- wearable->getDescription(), asset_type, inv_type, wearable->getType(),
- wearable->getPermissions().getMaskNextOwner(),
- LLPointer<LLInventoryCallback>(NULL));
-}
-
-void LLFolderBridge::modifyOutfit(BOOL append)
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLViewerInventoryCategory* cat = getCategory();
- if(!cat) return;
-
- // BAP - was:
- // wear_inventory_category_on_avatar( cat, append );
- LLAppearanceManager::wearInventoryCategory( cat, FALSE, append );
-}
-
-// helper stuff
-bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv)
-{
- LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData;
- LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID);
- S32 option = LLNotification::getSelectedOption(notification, response);
-
- if(option == 0 && object)
- {
- if (cat_and_wear && cat_and_wear->mWear)
- {
- InventoryObjectList inventory_objects;
- object->getInventoryContents(inventory_objects);
- int contents_count = inventory_objects.size()-1; //subtract one for containing folder
-
- LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count);
- gInventory.addObserver(inventoryObserver);
- }
-
- two_uuids_list_t::iterator move_it;
- for (move_it = move_inv->mMoveList.begin();
- move_it != move_inv->mMoveList.end();
- ++move_it)
- {
- object->moveInventory(move_it->first, move_it->second);
- }
-
- // update the UI.
- dialog_refresh_all();
- }
-
- if (move_inv->mCallback)
- {
- move_inv->mCallback(option, move_inv->mUserData);
- }
-
- delete move_inv;
- return false;
-}
-
-/*
-Next functions intended to reorder items in the inventory folder and save order on server
-Is now used for Favorites folder.
-
-*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel
-*/
-void saveItemsOrder(LLInventoryModel::item_array_t& items)
-{
- int sortField = 0;
-
- // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
- for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
- {
- LLViewerInventoryItem* item = *i;
-
- item->setSortField(++sortField);
- item->setComplete(TRUE);
- item->updateServer(FALSE);
-
- gInventory.updateItem(item);
- }
-
- gInventory.notifyObservers();
-}
-
-LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id)
-{
- LLInventoryModel::item_array_t::iterator result = items.end();
-
- for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
- {
- if ((*i)->getUUID() == id)
- {
- result = i;
- break;
- }
- }
-
- return result;
-}
-
-void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId)
-{
- LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId);
- LLViewerInventoryItem* destItem = gInventory.getItem(destItemId);
-
- items.erase(findItemByUUID(items, srcItem->getUUID()));
- items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
-}
-
-BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
- BOOL drop)
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
-
- // cannot drag into library
- if(!isAgentInventory())
- {
- return FALSE;
- }
-
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if(!avatar) return FALSE;
-
- LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
- BOOL accept = FALSE;
- LLViewerObject* object = NULL;
- if(LLToolDragAndDrop::SOURCE_AGENT == source)
- {
-
- BOOL is_movable = TRUE;
- switch( inv_item->getActualType() )
- {
- case LLAssetType::AT_ROOT_CATEGORY:
- is_movable = FALSE;
- break;
-
- case LLAssetType::AT_CATEGORY:
- is_movable = !LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)inv_item)->getPreferredType());
- break;
- default:
- break;
- }
-
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
- BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
- LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
- BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
- BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT);
-
- if(is_movable && move_is_into_trash)
- {
- switch(inv_item->getType())
- {
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_BODYPART:
- is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID());
- break;
-
- case LLAssetType::AT_OBJECT:
- is_movable = !avatar->isWearingAttachment(inv_item->getUUID());
- break;
- default:
- break;
- }
- }
-
- if ( is_movable )
- {
- // Don't allow creating duplicates in the Calling Card/Friends
- // subfolders, see bug EXT-1599. Check is item direct descendent
- // of target folder and forbid item's movement if it so.
- // Note: isItemDirectDescendentOfCategory checks if
- // passed category is in the Calling Card/Friends folder
- is_movable = ! LLFriendCardsManager::instance()
- .isObjDirectDescendentOfCategory (inv_item, getCategory());
- }
-
- LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
-
- // we can move item inside a folder only if this folder is Favorites. See EXT-719
- accept = is_movable && ((mUUID != inv_item->getParentUUID()) || (mUUID == favorites_id));
- if(accept && drop)
- {
- if (inv_item->getType() == LLAssetType::AT_GESTURE
- && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash)
- {
- LLGestureManager::instance().deactivateGesture(inv_item->getUUID());
- }
- // If an item is being dragged between windows, unselect
- // everything in the active window so that we don't follow
- // the selection to its new location (which is very
- // annoying).
- if (LLFloaterInventory::getActiveInventory())
- {
- LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- if (active_panel && (panel != active_panel))
- {
- active_panel->unSelectAll();
- }
- }
-
- // if dragging from/into favorites folder only reorder items
- if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID))
- {
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
- LLIsType is_type(LLAssetType::AT_LANDMARK);
- model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
-
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
- if (itemp)
- {
- LLUUID srcItemId = inv_item->getUUID();
- LLUUID destItemId = itemp->getListener()->getUUID();
-
- // update order
- updateItemsOrder(items, srcItemId, destItemId);
-
- saveItemsOrder(items);
- }
- }
- else if (favorites_id == mUUID) // if target is the favorites folder we use copy
- {
- copy_inventory_item(
- gAgent.getID(),
- inv_item->getPermissions().getOwner(),
- inv_item->getUUID(),
- mUUID,
- std::string(),
- LLPointer<LLInventoryCallback>(NULL));
- }
- else if (move_is_into_current_outfit || move_is_into_outfit)
- {
- // BAP - should skip if dup.
- if (move_is_into_current_outfit)
- {
- LLAppearanceManager::wearItem(inv_item);
- }
- else
- {
- LLPointer<LLInventoryCallback> cb = NULL;
- link_inventory_item(
- gAgent.getID(),
- inv_item->getUUID(),
- mUUID,
- std::string(),
- LLAssetType::AT_LINK,
- cb);
- }
- }
- else
- {
- // restamp if the move is into the trash.
- LLInvFVBridge::changeItemParent(
- model,
- (LLViewerInventoryItem*)inv_item,
- mUUID,
- move_is_into_trash);
- }
- }
- }
- else if(LLToolDragAndDrop::SOURCE_WORLD == source)
- {
- // Make sure the object exists. If we allowed dragging from
- // anonymous objects, it would be possible to bypass
- // permissions.
- object = gObjectList.findObject(inv_item->getParentUUID());
- if(!object)
- {
- llinfos << "Object not found for drop." << llendl;
- return FALSE;
- }
-
- // coming from a task. Need to figure out if the person can
- // move/copy this item.
- LLPermissions perm(inv_item->getPermissions());
- BOOL is_move = FALSE;
- if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
- && perm.allowTransferTo(gAgent.getID())))
-// || gAgent.isGodlike())
-
- {
- accept = TRUE;
- }
- else if(object->permYouOwner())
- {
- // If the object cannot be copied, but the object the
- // inventory is owned by the agent, then the item can be
- // moved from the task to agent inventory.
- is_move = TRUE;
- accept = TRUE;
- }
- if(drop && accept)
- {
- LLMoveInv* move_inv = new LLMoveInv;
- move_inv->mObjectID = inv_item->getParentUUID();
- two_uuids_t item_pair(mUUID, inv_item->getUUID());
- move_inv->mMoveList.push_back(item_pair);
- move_inv->mCallback = NULL;
- move_inv->mUserData = NULL;
- if(is_move)
- {
- warn_move_inventory(object, move_inv);
- }
- else
- {
- LLNotification::Params params("MoveInventoryFromObject");
- params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
- LLNotifications::instance().forceResponse(params, 0);
- }
- }
-
- }
- else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
- {
- accept = TRUE;
- if(drop)
- {
- copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(),
- LLToolDragAndDrop::getInstance()->getSourceID(), inv_item);
- }
- }
- else if(LLToolDragAndDrop::SOURCE_LIBRARY == source)
- {
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item;
- if(item && item->isComplete())
- {
- accept = TRUE;
- if(drop)
- {
- copy_inventory_item(
- gAgent.getID(),
- inv_item->getPermissions().getOwner(),
- inv_item->getUUID(),
- mUUID,
- std::string(),
- LLPointer<LLInventoryCallback>(NULL));
- }
- }
- }
- else
- {
- llwarns << "unhandled drag source" << llendl;
- }
- return accept;
-}
-
-// +=================================================+
-// | LLScriptBridge (DEPRECTED) |
-// +=================================================+
-
-LLUIImagePtr LLScriptBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
-}
-
-// +=================================================+
-// | LLTextureBridge |
-// +=================================================+
-
-LLUIImagePtr LLTextureBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE);
-}
-
-void LLTextureBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-}
-
-// +=================================================+
-// | LLSoundBridge |
-// +=================================================+
-
-LLUIImagePtr LLSoundBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE);
-}
-
-void LLSoundBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-/*
-// Changed this back to the way it USED to work:
-// only open the preview dialog through the contextual right-click menu
-// double-click just plays the sound
-
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- openSoundPreview((void*)this);
- //send_uuid_sound_trigger(item->getAssetUUID(), 1.0);
- }
-*/
-}
-
-void LLSoundBridge::previewItem()
-{
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- send_sound_trigger(item->getAssetUUID(), 1.0);
- }
-}
-
-void LLSoundBridge::openSoundPreview(void* which)
-{
- LLSoundBridge *me = (LLSoundBridge *)which;
- LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES);
-}
-
-void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- lldebugs << "LLTextureBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Sound Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
- }
-
- items.push_back(std::string("Sound Separator"));
- items.push_back(std::string("Sound Play"));
-
- hide_context_entries(menu, items, disabled_items);
-}
-
-// +=================================================+
-// | LLLandmarkBridge |
-// +=================================================+
-
-LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) :
-LLItemBridge(inventory, uuid)
-{
- mVisited = FALSE;
- if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
- {
- mVisited = TRUE;
- }
-}
-
-LLUIImagePtr LLLandmarkBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE);
-}
-
-void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl;
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Landmark Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
- }
-
- items.push_back(std::string("Landmark Separator"));
- items.push_back(std::string("About Landmark"));
-
- // Disable "About Landmark" menu item for
- // multiple landmarks selected. Only one landmark
- // info panel can be shown at a time.
- if ((flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("About Landmark"));
- }
-
- hide_context_entries(menu, items, disabled_items);
-}
-
-// Convenience function for the two functions below.
-void teleport_via_landmark(const LLUUID& asset_id)
-{
- gAgent.teleportViaLandmark( asset_id );
-
- // we now automatically track the landmark you're teleporting to
- // because you'll probably arrive at a telehub instead
- LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance();
- if( floater_world_map )
- {
- floater_world_map->trackLandmark( asset_id );
- }
-}
-
-// virtual
-void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("teleport" == action)
- {
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- teleport_via_landmark(item->getAssetUUID());
- }
- }
- else if ("about" == action)
- {
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- LLSD key;
- key["type"] = "landmark";
- key["id"] = item->getUUID();
-
- LLSideTray::getInstance()->showPanel("panel_places", key);
- }
- }
- else
- {
- LLItemBridge::performAction(folder, model, action);
- }
-}
-
-static bool open_landmark_callback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
-
- LLUUID asset_id = notification["payload"]["asset_id"].asUUID();
- if (option == 0)
- {
- teleport_via_landmark(asset_id);
- }
-
- return false;
-}
-static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback);
-
-
-void LLLandmarkBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-/*
- LLViewerInventoryItem* item = getItem();
- if( item )
- {
- // Opening (double-clicking) a landmark immediately teleports,
- // but warns you the first time.
- // open_landmark(item);
- LLSD payload;
- payload["asset_id"] = item->getAssetUUID();
- LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
- }
-*/
-}
-
-
-// +=================================================+
-// | LLCallingCardObserver |
-// +=================================================+
-void LLCallingCardObserver::changed(U32 mask)
-{
- mBridgep->refreshFolderViewItem();
-}
-
-// +=================================================+
-// | LLCallingCardBridge |
-// +=================================================+
-
-LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) :
- LLItemBridge(inventory, uuid)
-{
- mObserver = new LLCallingCardObserver(this);
- LLAvatarTracker::instance().addObserver(mObserver);
-}
-
-LLCallingCardBridge::~LLCallingCardBridge()
-{
- LLAvatarTracker::instance().removeObserver(mObserver);
- delete mObserver;
-}
-
-void LLCallingCardBridge::refreshFolderViewItem()
-{
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL;
- if (itemp)
- {
- itemp->refresh();
- }
-}
-
-// virtual
-void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("begin_im" == action)
- {
- LLViewerInventoryItem *item = getItem();
- if (item && (item->getCreatorUUID() != gAgent.getID()) &&
- (!item->getCreatorUUID().isNull()))
- {
- std::string callingcard_name;
- gCacheName->getFullName(item->getCreatorUUID(), callingcard_name);
- gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
- }
- }
- else if ("lure" == action)
- {
- LLViewerInventoryItem *item = getItem();
- if (item && (item->getCreatorUUID() != gAgent.getID()) &&
- (!item->getCreatorUUID().isNull()))
- {
- LLAvatarActions::offerTeleport(item->getCreatorUUID());
- }
- }
- else LLItemBridge::performAction(folder, model, action);
-}
-
-LLUIImagePtr LLCallingCardBridge::getIcon() const
-{
- BOOL online = FALSE;
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID());
- }
- return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE);
-}
-
-std::string LLCallingCardBridge::getLabelSuffix() const
-{
- LLViewerInventoryItem* item = getItem();
- if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) )
- {
- return LLItemBridge::getLabelSuffix() + " (online)";
- }
- else
- {
- return LLItemBridge::getLabelSuffix();
- }
-}
-
-void LLCallingCardBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-/*
- LLViewerInventoryItem* item = getItem();
- if(item && !item->getCreatorUUID().isNull())
- {
- LLAvatarActions::showProfile(item->getCreatorUUID());
- }
-*/
-}
-
-void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
-
- LLInventoryItem* item = getItem();
- BOOL good_card = (item
- && (LLUUID::null != item->getCreatorUUID())
- && (item->getCreatorUUID() != gAgent.getID()));
- BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()));
- items.push_back(std::string("Send Instant Message Separator"));
- items.push_back(std::string("Send Instant Message"));
- items.push_back(std::string("Offer Teleport..."));
- items.push_back(std::string("Conference Chat"));
-
- if (!good_card)
- {
- disabled_items.push_back(std::string("Send Instant Message"));
- }
- if (!good_card || !user_online)
- {
- disabled_items.push_back(std::string("Offer Teleport..."));
- disabled_items.push_back(std::string("Conference Chat"));
- }
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data)
-{
- LLViewerInventoryItem* item = getItem();
- BOOL rv = FALSE;
- if(item)
- {
- // check the type
- switch(cargo_type)
- {
- case DAD_TEXTURE:
- case DAD_SOUND:
- case DAD_LANDMARK:
- case DAD_SCRIPT:
- case DAD_CLOTHING:
- case DAD_OBJECT:
- case DAD_NOTECARD:
- case DAD_BODYPART:
- case DAD_ANIMATION:
- case DAD_GESTURE:
- {
- LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
- const LLPermissions& perm = inv_item->getPermissions();
- if(gInventory.getItem(inv_item->getUUID())
- && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID()))
- {
- rv = TRUE;
- if(drop)
- {
- LLToolDragAndDrop::giveInventory(item->getCreatorUUID(),
- (LLInventoryItem*)cargo_data);
- }
- }
- else
- {
- // It's not in the user's inventory (it's probably in
- // an object's contents), so disallow dragging it here.
- // You can't give something you don't yet have.
- rv = FALSE;
- }
- break;
- }
- case DAD_CATEGORY:
- {
- LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data;
- if( gInventory.getCategory( inv_cat->getUUID() ) )
- {
- rv = TRUE;
- if(drop)
- {
- LLToolDragAndDrop::giveInventoryCategory(
- item->getCreatorUUID(),
- inv_cat);
- }
- }
- else
- {
- // It's not in the user's inventory (it's probably in
- // an object's contents), so disallow dragging it here.
- // You can't give something you don't yet have.
- rv = FALSE;
- }
- break;
- }
- default:
- break;
- }
- }
- return rv;
-}
-
-BOOL LLCallingCardBridge::removeItem()
-{
- if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem()))
- {
- LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
- return FALSE;
- }
- else
- {
- return LLItemBridge::removeItem();
- }
-}
-// +=================================================+
-// | LLNotecardBridge |
-// +=================================================+
-
-LLUIImagePtr LLNotecardBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE);
-}
-
-void LLNotecardBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-
-/*
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
- }
-*/
-}
-
-
-// +=================================================+
-// | LLGestureBridge |
-// +=================================================+
-
-LLUIImagePtr LLGestureBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE);
-}
-
-LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const
-{
- if( LLGestureManager::instance().isGestureActive(mUUID) )
- {
- return LLFontGL::BOLD;
- }
- else
- {
- return LLFontGL::NORMAL;
- }
-}
-
-std::string LLGestureBridge::getLabelSuffix() const
-{
- if( LLGestureManager::instance().isGestureActive(mUUID) )
- {
- return LLItemBridge::getLabelSuffix() + " (active)";
- }
- else
- {
- return LLItemBridge::getLabelSuffix();
- }
-}
-
-// virtual
-void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("activate" == action)
- {
- LLGestureManager::instance().activateGesture(mUUID);
-
- LLViewerInventoryItem* item = gInventory.getItem(mUUID);
- if (!item) return;
-
- // Since we just changed the suffix to indicate (active)
- // the server doesn't need to know, just the viewer.
- gInventory.updateItem(item);
- gInventory.notifyObservers();
- }
- else if ("deactivate" == action)
- {
- LLGestureManager::instance().deactivateGesture(mUUID);
-
- LLViewerInventoryItem* item = gInventory.getItem(mUUID);
- if (!item) return;
-
- // Since we just changed the suffix to indicate (active)
- // the server doesn't need to know, just the viewer.
- gInventory.updateItem(item);
- gInventory.notifyObservers();
- }
- else LLItemBridge::performAction(folder, model, action);
-}
-
-void LLGestureBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-/*
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
- preview->setFocus(TRUE);
- }
-*/
-}
-
-BOOL LLGestureBridge::removeItem()
-{
- // Force close the preview window, if it exists
- LLGestureManager::instance().deactivateGesture(mUUID);
- return LLItemBridge::removeItem();
-}
-
-void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- lldebugs << "LLGestureBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
-
- items.push_back(std::string("Gesture Separator"));
- items.push_back(std::string("Activate"));
- items.push_back(std::string("Deactivate"));
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-// +=================================================+
-// | LLAnimationBridge |
-// +=================================================+
-
-LLUIImagePtr LLAnimationBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE);
-}
-
-void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl;
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Animation Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
- }
-
- items.push_back(std::string("Animation Separator"));
- items.push_back(std::string("Animation Play"));
- items.push_back(std::string("Animation Audition"));
-
- hide_context_entries(menu, items, disabled_items);
-
-}
-
-// virtual
-void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ((action == "playworld") || (action == "playlocal"))
- {
- if (getItem())
- {
- LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE;
- if ("playworld" == action) activate = LLPreviewAnim::PLAY;
- if ("playlocal" == action) activate = LLPreviewAnim::AUDITION;
-
- LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID));
- if (preview)
- {
- preview->activate(activate);
- }
- }
- }
- else
- {
- LLItemBridge::performAction(folder, model, action);
- }
-}
-
-void LLAnimationBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-/*
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
- }
-*/
-}
-
-// +=================================================+
-// | LLObjectBridge |
-// +=================================================+
-
-// static
-LLUUID LLObjectBridge::sContextMenuItemID;
-
-LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) :
-LLItemBridge(inventory, uuid), mInvType(type)
-{
- mAttachPt = (flags & 0xff); // low bye of inventory flags
-
- mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE;
-}
-
-BOOL LLObjectBridge::isItemRemovable()
-{
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if(!avatar) return FALSE;
- if(avatar->isWearingAttachment(mUUID)) return FALSE;
- return LLInvFVBridge::isItemRemovable();
-}
-
-LLUIImagePtr LLObjectBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject );
-}
-
-LLInventoryObject* LLObjectBridge::getObject() const
-{
- LLInventoryObject* object = NULL;
- LLInventoryModel* model = getInventoryModel();
- if(model)
- {
- object = (LLInventoryObject*)model->getObject(mUUID);
- }
- return object;
-}
-
-// virtual
-void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("attach" == action)
- {
- LLUUID object_id = mUUID;
- LLViewerInventoryItem* item;
- item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
- if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID()))
- {
- rez_attachment(item, NULL);
- }
- else if(item && item->isComplete())
- {
- // must be in library. copy it to our inventory and put it on.
- LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0);
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- gFocusMgr.setKeyboardFocus(NULL);
- }
- else if ("detach" == action)
- {
- LLInventoryItem* item = gInventory.getItem(mUUID);
- if(item)
- {
- gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
- gMessageSystem->sendReliable( gAgent.getRegion()->getHost());
- }
- // this object might have been selected, so let the selection manager know it's gone now
- LLViewerObject *found_obj =
- gObjectList.findObject(item->getUUID());
- if (found_obj)
- {
- LLSelectMgr::getInstance()->remove(found_obj);
- }
- else
- {
- llwarns << "object not found - ignoring" << llendl;
- }
- }
- else LLItemBridge::performAction(folder, model, action);
-}
-
-void LLObjectBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-
- LLSD key;
- key["id"] = mUUID;
- LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
-
- /*
- LLFloaterReg::showInstance("properties", mUUID);
- */
-}
-
-LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
-{
- U8 font = LLFontGL::NORMAL;
-
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if( avatar && avatar->isWearingAttachment( mUUID ) )
- {
- font |= LLFontGL::BOLD;
- }
-
- LLInventoryItem* item = getItem();
- if (item && item->getIsLinkType())
- {
- font |= LLFontGL::ITALIC;
- }
-
- return (LLFontGL::StyleFlags)font;
-}
-
-std::string LLObjectBridge::getLabelSuffix() const
-{
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if( avatar && avatar->isWearingAttachment( mUUID ) )
- {
- std::string attachment_point_name = avatar->getAttachedPointName(mUUID);
- LLStringUtil::toLower(attachment_point_name);
-
- LLStringUtil::format_map_t args;
- args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str();
- return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args);
- }
- else
- {
- return LLItemBridge::getLabelSuffix();
- }
-}
-
-void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment)
-{
- LLSD payload;
- payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link.
-
- S32 attach_pt = 0;
- if (gAgent.getAvatarObject() && attachment)
- {
- for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin();
- iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter)
- {
- if (iter->second == attachment)
- {
- attach_pt = iter->first;
- break;
- }
- }
- }
-
- payload["attachment_point"] = attach_pt;
-
-#if !ENABLE_MULTIATTACHMENTS
- if (attachment && attachment->getNumObjects() > 0)
- {
- LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez);
- }
- else
-#endif
- {
- LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
- }
-}
-
-bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response)
-{
- LLVOAvatar *avatarp = gAgent.getAvatarObject();
-
- if (!avatarp->canAttachMoreObjects())
- {
- LLSD args;
- args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS);
- LLNotifications::instance().add("MaxAttachmentsOnOutfit", args);
- return false;
- }
-
- S32 option = LLNotification::getSelectedOption(notification, response);
- if (option == 0/*YES*/)
- {
- LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
-
- if (itemp)
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID());
- msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner());
- U8 attachment_pt = notification["payload"]["attachment_point"].asInteger();
-#if ENABLE_MULTIATTACHMENTS
- attachment_pt |= ATTACHMENT_ADD;
-#endif
- msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt);
- pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions());
- msg->addStringFast(_PREHASH_Name, itemp->getName());
- msg->addStringFast(_PREHASH_Description, itemp->getDescription());
- msg->sendReliable(gAgent.getRegion()->getHost());
- }
- }
- return false;
-}
-static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_replace_attachment_rez);
-
-void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- LLInventoryItem* item = getItem();
- if (item && item->getIsLinkType())
- {
- items.push_back(std::string("Goto Link"));
- }
-
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
-
- LLObjectBridge::sContextMenuItemID = mUUID;
-
- if(item)
- {
- LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
- if( !avatarp )
- {
- return;
- }
-
- if( avatarp->isWearingAttachment( mUUID ) )
- {
- items.push_back(std::string("Detach From Yourself"));
- }
- else
- if( !isInTrash() && !isLinkedObjectInTrash() )
- {
- items.push_back(std::string("Attach Separator"));
- items.push_back(std::string("Object Wear"));
- items.push_back(std::string("Attach To"));
- items.push_back(std::string("Attach To HUD"));
- // commented out for DEV-32347
- //items.push_back(std::string("Restore to Last Position"));
-
- if (!avatarp->canAttachMoreObjects())
- {
- disabled_items.push_back(std::string("Object Wear"));
- disabled_items.push_back(std::string("Attach To"));
- disabled_items.push_back(std::string("Attach To HUD"));
- }
- LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE);
- LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE);
- LLVOAvatar *avatarp = gAgent.getAvatarObject();
- if (attach_menu
- && (attach_menu->getChildCount() == 0)
- && attach_hud_menu
- && (attach_hud_menu->getChildCount() == 0)
- && avatarp)
- {
- for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
- iter != avatarp->mAttachmentPoints.end(); )
- {
- LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- LLMenuItemCallGL::Params p;
- std::string submenu_name = attachment->getName();
- if (LLTrans::getString(submenu_name) != "")
- {
- p.name = (" ")+LLTrans::getString(submenu_name)+" ";
- }
- else
- {
- p.name = submenu_name;
- }
- LLSD cbparams;
- cbparams["index"] = curiter->first;
- cbparams["label"] = attachment->getName();
- p.on_click.function_name = "Inventory.AttachObject";
- p.on_click.parameter = LLSD(attachment->getName());
- p.on_enable.function_name = "Attachment.Label";
- p.on_enable.parameter = cbparams;
- LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu;
- LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);
- }
- }
- }
- }
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-BOOL LLObjectBridge::renameItem(const std::string& new_name)
-{
- if(!isItemRenameable())
- return FALSE;
- LLPreview::dirty(mUUID);
- LLInventoryModel* model = getInventoryModel();
- if(!model)
- return FALSE;
- LLViewerInventoryItem* item = getItem();
- if(item && (item->getName() != new_name))
- {
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
- new_item->rename(new_name);
- buildDisplayName(new_item, mDisplayName);
- new_item->updateServer(FALSE);
- model->updateItem(new_item);
-
- model->notifyObservers();
-
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if( avatar )
- {
- LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
- if( obj )
- {
- LLSelectMgr::getInstance()->deselectAll();
- LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
- LLSelectMgr::getInstance()->selectionSetObjectName( new_name );
- LLSelectMgr::getInstance()->deselectAll();
- }
- }
- }
- // return FALSE because we either notified observers (& therefore
- // rebuilt) or we didn't update.
- return FALSE;
-}
-
-// +=================================================+
-// | LLLSLTextBridge |
-// +=================================================+
-
-LLUIImagePtr LLLSLTextBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
-}
-
-void LLLSLTextBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
- /*
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
- }
- */
-}
-
-// +=================================================+
-// | LLWearableBridge |
-// +=================================================+
-
-// *NOTE: hack to get from avatar inventory to avatar
-void wear_inventory_item_on_avatar( LLInventoryItem* item )
-{
- if(item)
- {
- lldebugs << "wear_inventory_item_on_avatar( " << item->getName()
- << " )" << llendl;
-
- LLAppearanceManager::wearItem(item);
- }
-}
-
-void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
-{
- if(item)
- {
- lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName()
- << " )" << llendl;
-
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onWearAddOnAvatarArrived,
- new LLUUID(item->getUUID()));
- }
-}
-
-void remove_inventory_category_from_avatar( LLInventoryCategory* category )
-{
- if(!category) return;
- lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
- << " )" << llendl;
-
-
- if( gFloaterCustomize )
- {
- gFloaterCustomize->askToSaveIfDirty(
- boost::bind(remove_inventory_category_from_avatar_step2, _1, category->getUUID()));
- }
- else
- {
- remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() );
- }
-}
-
-struct OnRemoveStruct
-{
- LLUUID mUUID;
- OnRemoveStruct(const LLUUID& uuid):
- mUUID(uuid)
- {
- }
-};
-
-void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id)
-{
-
- // Find all the wearables that are in the category's subtree.
- lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl;
- if(proceed)
- {
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- LLFindWearables is_wearable;
- gInventory.collectDescendentsIf(category_id,
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_wearable);
- S32 i;
- S32 wearable_count = item_array.count();
-
- LLInventoryModel::cat_array_t obj_cat_array;
- LLInventoryModel::item_array_t obj_item_array;
- LLIsType is_object( LLAssetType::AT_OBJECT );
- gInventory.collectDescendentsIf(category_id,
- obj_cat_array,
- obj_item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_object);
- S32 obj_count = obj_item_array.count();
-
- // Find all gestures in this folder
- LLInventoryModel::cat_array_t gest_cat_array;
- LLInventoryModel::item_array_t gest_item_array;
- LLIsType is_gesture( LLAssetType::AT_GESTURE );
- gInventory.collectDescendentsIf(category_id,
- gest_cat_array,
- gest_item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_gesture);
- S32 gest_count = gest_item_array.count();
-
- if (wearable_count > 0) //Loop through wearables. If worn, remove.
- {
- for(i = 0; i < wearable_count; ++i)
- {
- if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) )
- {
- LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(),
- item_array.get(i)->getName(),
- item_array.get(i)->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new OnRemoveStruct(item_array.get(i)->getUUID()));
-
- }
- }
- }
-
-
- if (obj_count > 0)
- {
- for(i = 0; i < obj_count; ++i)
- {
- gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() );
-
- gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
-
- // this object might have been selected, so let the selection manager know it's gone now
- LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID());
- if (found_obj)
- {
- LLSelectMgr::getInstance()->remove(found_obj);
- }
- else
- {
- llwarns << "object not found, ignoring" << llendl;
- }
- }
- }
-
- if (gest_count > 0)
- {
- for(i = 0; i < gest_count; ++i)
- {
- if ( LLGestureManager::instance().isGestureActive( gest_item_array.get(i)->getUUID()) )
- {
- LLGestureManager::instance().deactivateGesture( gest_item_array.get(i)->getUUID() );
- gInventory.updateItem( gest_item_array.get(i) );
- gInventory.notifyObservers();
- }
-
- }
- }
- }
-}
-
-BOOL LLWearableBridge::renameItem(const std::string& new_name)
-{
- if( gAgentWearables.isWearingItem( mUUID ) )
- {
- gAgentWearables.setWearableName( mUUID, new_name );
- }
- return LLItemBridge::renameItem(new_name);
-}
-
-BOOL LLWearableBridge::isItemRemovable()
-{
- if (gAgentWearables.isWearingItem(mUUID)) return FALSE;
- return LLInvFVBridge::isItemRemovable();
-}
-
-std::string LLWearableBridge::getLabelSuffix() const
-{
- if( gAgentWearables.isWearingItem( mUUID ) )
- {
- return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");
- }
- else
- {
- return LLItemBridge::getLabelSuffix();
- }
-}
-
-LLUIImagePtr LLWearableBridge::getIcon() const
-{
- return get_item_icon(mAssetType, mInvType, mWearableType, FALSE);
-}
-
-// virtual
-void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("wear" == action)
- {
- wearOnAvatar();
- }
- else if ("wear_add" == action)
- {
- wearAddOnAvatar();
- }
- else if ("edit" == action)
- {
- editOnAvatar();
- return;
- }
- else if ("take_off" == action)
- {
- if(gAgentWearables.isWearingItem(mUUID))
- {
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new OnRemoveStruct(mUUID));
- }
- }
- }
- else LLItemBridge::performAction(folder, model, action);
-}
-
-void LLWearableBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
- /*
- if( isInTrash() )
- {
- LLNotifications::instance().add("CannotWearTrash");
- }
- else if(isAgentInventory())
- {
- if( !gAgentWearables.isWearingItem( mUUID ) )
- {
- wearOnAvatar();
- }
- }
- else
- {
- // must be in the inventory library. copy it to our inventory
- // and put it on right away.
- LLViewerInventoryItem* item = getItem();
- if(item && item->isComplete())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else if(item)
- {
- // *TODO: We should fetch the item details, and then do
- // the operation above.
- LLNotifications::instance().add("CannotWearInfoNotComplete");
- }
- }
- */
-}
-
-void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- lldebugs << "LLWearableBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere
- BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM);
-
- // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976
- LLViewerInventoryItem* item = getItem();
- if( !no_open && item )
- {
- no_open = (item->getType() == LLAssetType::AT_CLOTHING) ||
- (item->getType() == LLAssetType::AT_BODYPART);
- }
- if (!no_open)
- {
- items.push_back(std::string("Open"));
- }
-
- if (item && item->getIsLinkType())
- {
- items.push_back(std::string("Goto Link"));
- }
-
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
-
- items.push_back(std::string("Wearable Separator"));
-
- items.push_back(std::string("Wearable Wear"));
- items.push_back(std::string("Wearable Add"));
- items.push_back(std::string("Wearable Edit"));
-
- if ((flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Wearable Edit"));
- }
- // Don't allow items to be worn if their baseobj is in the trash.
- if (isLinkedObjectInTrash())
- {
- disabled_items.push_back(std::string("Wearable Wear"));
- disabled_items.push_back(std::string("Wearable Add"));
- disabled_items.push_back(std::string("Wearable Edit"));
- }
-
- // Disable wear and take off based on whether the item is worn.
- if(item)
- {
- switch (item->getType())
- {
- case LLAssetType::AT_CLOTHING:
- items.push_back(std::string("Take Off"));
- case LLAssetType::AT_BODYPART:
- if (gAgentWearables.isWearingItem(item->getUUID()))
- {
- disabled_items.push_back(std::string("Wearable Wear"));
- disabled_items.push_back(std::string("Wearable Add"));
- }
- else
- {
- disabled_items.push_back(std::string("Take Off"));
- }
- break;
- default:
- break;
- }
- }
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-// Called from menus
-// static
-BOOL LLWearableBridge::canWearOnAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if(!self) return FALSE;
- if(!self->isAgentInventory())
- {
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem();
- if(!item || !item->isComplete()) return FALSE;
- }
- return (!gAgentWearables.isWearingItem(self->mUUID));
-}
-
-// Called from menus
-// static
-void LLWearableBridge::onWearOnAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if(!self) return;
- self->wearOnAvatar();
-}
-
-void LLWearableBridge::wearOnAvatar()
-{
- // Don't wear anything until initial wearables are loaded, can
- // destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
- {
- LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
- return;
- }
-
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- if(!isAgentInventory())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else
- {
- wear_inventory_item_on_avatar(item);
- }
- }
-}
-
-void LLWearableBridge::wearAddOnAvatar()
-{
- // Don't wear anything until initial wearables are loaded, can
- // destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
- {
- LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
- return;
- }
-
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- if(!isAgentInventory())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else
- {
- wear_add_inventory_item_on_avatar(item);
- }
- }
-}
-
-// static
-void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata )
-{
- LLUUID* item_id = (LLUUID*) userdata;
- if(wearable)
- {
- LLViewerInventoryItem* item = NULL;
- item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
- if(item)
- {
- if(item->getAssetUUID() == wearable->getAssetID())
- {
- gAgentWearables.setWearableItem(item, wearable);
- gInventory.notifyObservers();
- //self->getFolderItem()->refreshFromRoot();
- }
- else
- {
- llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
- }
- }
- }
- delete item_id;
-}
-
-// static
-// BAP remove the "add" code path once everything is fully COF-ified.
-void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata )
-{
- LLUUID* item_id = (LLUUID*) userdata;
- if(wearable)
- {
- LLViewerInventoryItem* item = NULL;
- item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
- if(item)
- {
- if(item->getAssetUUID() == wearable->getAssetID())
- {
- bool do_append = true;
- gAgentWearables.setWearableItem(item, wearable, do_append);
- gInventory.notifyObservers();
- //self->getFolderItem()->refreshFromRoot();
- }
- else
- {
- llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
- }
- }
- }
- delete item_id;
-}
-
-// static
-BOOL LLWearableBridge::canEditOnAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if(!self) return FALSE;
-
- return (gAgentWearables.isWearingItem(self->mUUID));
-}
-
-// static
-void LLWearableBridge::onEditOnAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if(self)
- {
- self->editOnAvatar();
- }
-}
-
-void LLWearableBridge::editOnAvatar()
-{
- const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID);
- if( wearable )
- {
- // Set the tab to the right wearable.
- if (gFloaterCustomize)
- gFloaterCustomize->setCurrentWearableType( wearable->getType() );
-
- if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() )
- {
- // Start Avatar Customization
- gAgent.changeCameraToCustomizeAvatar();
- }
- }
-}
-
-// static
-BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if( self && (LLAssetType::AT_BODYPART != self->mAssetType) )
- {
- return gAgentWearables.isWearingItem( self->mUUID );
- }
- return FALSE;
-}
-
-// static
-void LLWearableBridge::onRemoveFromAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if(!self) return;
- if(gAgentWearables.isWearingItem(self->mUUID))
- {
- LLViewerInventoryItem* item = self->getItem();
- if (item)
- {
- LLUUID parent_id = item->getParentUUID();
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- onRemoveFromAvatarArrived,
- new OnRemoveStruct(LLUUID(self->mUUID)));
- }
- }
-}
-
-// static
-void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
- void* userdata)
-{
- OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata;
- const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID);
- if(wearable)
- {
- if( gAgentWearables.isWearingItem( item_id ) )
- {
- EWearableType type = wearable->getType();
-
- if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&&
- //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) )
- {
- // MULTI_WEARABLE: FIXME HACK - always remove all
- bool do_remove_all = false;
- gAgentWearables.removeWearable( type, do_remove_all, 0 );
- }
- }
- }
-
- // Find and remove this item from the COF.
- LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::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();
-
- delete on_remove_struct;
-}
-
-LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
- const LLUUID& uuid,LLInventoryModel* model)
-{
- LLInvFVBridgeAction* action = NULL;
- switch(asset_type)
- {
- case LLAssetType::AT_TEXTURE:
- action = new LLTextureBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_SOUND:
- action = new LLSoundBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_LANDMARK:
- action = new LLLandmarkBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_CALLINGCARD:
- action = new LLCallingCardBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_OBJECT:
- action = new LLObjectBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_NOTECARD:
- action = new LLNotecardBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_ANIMATION:
- action = new LLAnimationBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_GESTURE:
- action = new LLGestureBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_LSL_TEXT:
- action = new LLLSLTextBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_BODYPART:
- action = new LLWearableBridgeAction(uuid,model);
-
- break;
-
- default:
- break;
- }
- return action;
-}
-
-//static
-void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
- const LLUUID& uuid,LLInventoryModel* model)
-{
- LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
- if(action)
- {
- action->doIt();
- delete action;
- }
-}
-
-//static
-void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model)
-{
- LLAssetType::EType asset_type = model->getItem(uuid)->getType();
- LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
- if(action)
- {
- action->doIt();
- delete action;
- }
-}
-
-LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const
-{
- if(mModel)
- return (LLViewerInventoryItem*)mModel->getItem(mUUID);
- return NULL;
-}
-
-//virtual
-void LLTextureBridgeAction::doIt()
-{
- if (getItem())
- {
- LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-//virtual
-void LLSoundBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-
-//virtual
-void LLLandmarkBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if( item )
- {
- // Opening (double-clicking) a landmark immediately teleports,
- // but warns you the first time.
- LLSD payload;
- payload["asset_id"] = item->getAssetUUID();
- LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-
-//virtual
-void LLCallingCardBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if(item && item->getCreatorUUID().notNull())
- {
- LLAvatarActions::showProfile(item->getCreatorUUID());
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-//virtual
-void
-LLNotecardBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-//virtual
-void LLGestureBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
- preview->setFocus(TRUE);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-//virtual
-void LLAnimationBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-
-//virtual
-void LLObjectBridgeAction::doIt()
-{
- LLFloaterReg::showInstance("properties", mUUID);
-
- LLInvFVBridgeAction::doIt();
-}
-
-
-//virtual
-void LLLSLTextBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-
-BOOL LLWearableBridgeAction::isInTrash() const
-{
- if(!mModel) return FALSE;
- LLUUID trash_id = mModel->findCategoryUUIDForType(LLAssetType::AT_TRASH);
- return mModel->isObjectDescendentOf(mUUID, trash_id);
-}
-
-BOOL LLWearableBridgeAction::isAgentInventory() const
-{
- if(!mModel) return FALSE;
- if(gInventory.getRootFolderID() == mUUID) return TRUE;
- return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
-}
-
-void LLWearableBridgeAction::wearOnAvatar()
-{
- // Don't wear anything until initial wearables are loaded, can
- // destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
- {
- LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
- return;
- }
-
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- if(!isAgentInventory())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else
- {
- wear_inventory_item_on_avatar(item);
- }
- }
-}
-
-//virtual
-void LLWearableBridgeAction::doIt()
-{
- if(isInTrash())
- {
- LLNotifications::instance().add("CannotWearTrash");
- }
- else if(isAgentInventory())
- {
- if(!gAgentWearables.isWearingItem(mUUID))
- {
- wearOnAvatar();
- }
- }
- else
- {
- // must be in the inventory library. copy it to our inventory
- // and put it on right away.
- LLViewerInventoryItem* item = getItem();
- if(item && item->isComplete())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else if(item)
- {
- // *TODO: We should fetch the item details, and then do
- // the operation above.
- LLNotifications::instance().add("CannotWearInfoNotComplete");
- }
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-// +=================================================+
-// | LLLinkItemBridge |
-// +=================================================+
-// For broken links
-
-std::string LLLinkItemBridge::sPrefix("Link: ");
-
-
-LLUIImagePtr LLLinkItemBridge::getIcon() const
-{
- if (LLViewerInventoryItem *item = getItem())
- {
- return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE);
- }
- return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE);
-}
-
-void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- // *TODO: Translate
- lldebugs << "LLLink::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Delete"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Delete"));
- }
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-
-// +=================================================+
-// | LLLinkBridge |
-// +=================================================+
-// For broken links.
-
-std::string LLLinkFolderBridge::sPrefix("Link: ");
-
-
-LLUIImagePtr LLLinkFolderBridge::getIcon() const
-{
- LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
- if (LLViewerInventoryItem *item = getItem())
- {
- if (const LLViewerInventoryCategory* cat = item->getLinkedCategory())
- {
- preferred_type = cat->getPreferredType();
- }
- }
- return LLFolderBridge::getIcon(preferred_type);
-}
-
-void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- // *TODO: Translate
- lldebugs << "LLLink::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Goto Link"));
- items.push_back(std::string("Delete"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Delete"));
- }
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("goto" == action)
- {
- gotoItem(folder);
- return;
- }
- LLItemBridge::performAction(folder,model,action);
-}
-
-void LLLinkFolderBridge::gotoItem(LLFolderView *folder)
-{
- const LLUUID &cat_uuid = getFolderID();
- if (!cat_uuid.isNull())
- {
- if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid))
- {
- if (LLInventoryModel* model = getInventoryModel())
- {
- model->fetchDescendentsOf(cat_uuid);
- }
- base_folder->setOpen(TRUE);
- folder->setSelectionFromRoot(base_folder,TRUE);
- folder->scrollToShowSelection();
- }
- }
-}
-
-const LLUUID &LLLinkFolderBridge::getFolderID() const
-{
- if (LLViewerInventoryItem *link_item = getItem())
- {
- if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory())
- {
- const LLUUID& cat_uuid = cat->getUUID();
- return cat_uuid;
- }
- }
- return LLUUID::null;
-}
+/** + * @file llinventorybridge.cpp + * @brief Implementation of the Inventory-Folder-View-Bridge classes. + * + * $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 <utility> // for std::pair<> + +#include "llfloaterinventory.h" +#include "llinventorybridge.h" + +#include "message.h" + +#include "llagent.h" +#include "llagentwearables.h" +#include "llcallingcard.h" +#include "llcheckboxctrl.h" // for radio buttons +#include "llfloaterreg.h" +#include "llradiogroup.h" +#include "llspinctrl.h" +#include "lltextbox.h" +#include "llui.h" + +#include "llviewercontrol.h" +#include "llfirstuse.h" +#include "llfoldertype.h" +#include "llfloaterchat.h" +#include "llfloatercustomize.h" +#include "llfloaterproperties.h" +#include "llfloaterworldmap.h" +#include "llfocusmgr.h" +#include "llfolderview.h" +#include "llfriendcard.h" +#include "llavataractions.h" +#include "llgesturemgr.h" +#include "lliconctrl.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "llinventorypanel.h" +#include "llinventoryclipboard.h" +#include "lllineeditor.h" +#include "llmenugl.h" +#include "llpreviewanim.h" +#include "llpreviewgesture.h" +#include "llpreviewnotecard.h" +#include "llpreviewscript.h" +#include "llpreviewsound.h" +#include "llpreviewtexture.h" +#include "llresmgr.h" +#include "llscrollcontainer.h" +#include "llimview.h" +#include "lltooldraganddrop.h" +#include "llviewertexturelist.h" +#include "llviewerinventory.h" +#include "llviewerobjectlist.h" +#include "llviewerwindow.h" +#include "llvoavatar.h" +#include "llwearable.h" +#include "llwearablelist.h" +#include "llviewermessage.h" +#include "llviewerregion.h" +#include "llvoavatarself.h" +#include "lltabcontainer.h" +#include "lluictrlfactory.h" +#include "llselectmgr.h" +#include "llsidetray.h" +#include "llfloateropenobject.h" +#include "lltrans.h" +#include "llappearancemgr.h" + +using namespace LLOldEvents; + +// Helpers +// bug in busy count inc/dec right now, logic is complex... do we really need it? +void inc_busy_count() +{ +// gViewerWindow->getWindow()->incBusyCount(); +// check balance of these calls if this code is changed to ever actually +// *do* something! +} +void dec_busy_count() +{ +// gViewerWindow->getWindow()->decBusyCount(); +// check balance of these calls if this code is changed to ever actually +// *do* something! +} + +// Function declarations +void wear_add_inventory_item_on_avatar(LLInventoryItem* item); +void remove_inventory_category_from_avatar(LLInventoryCategory* category); +void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id); +bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*); +bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response); + +std::string ICON_NAME[ICON_NAME_COUNT] = +{ + "Inv_Texture", + "Inv_Sound", + "Inv_CallingCard", + "Inv_CallingCard", + "Inv_Landmark", + "Inv_Landmark", + "Inv_Script", + "Inv_Clothing", + "Inv_Object", + "Inv_Object", + "Inv_Notecard", + "Inv_Skin", + "Inv_Snapshot", + + "Inv_BodyShape", + "Inv_Skin", + "Inv_Hair", + "Inv_Eye", + "Inv_Shirt", + "Inv_Pants", + "Inv_Shoe", + "Inv_Socks", + "Inv_Jacket", + "Inv_Gloves", + "Inv_Undershirt", + "Inv_Underpants", + "Inv_Skirt", + "Inv_Alpha", + "Inv_Tattoo", + + "Inv_Animation", + "Inv_Gesture", + + "inv_item_linkitem.tga", + "inv_item_linkfolder.tga" +}; + + +// +=================================================+ +// | LLInventoryPanelObserver | +// +=================================================+ +void LLInventoryPanelObserver::changed(U32 mask) +{ + mIP->modelChanged(mask); +} + + +// +=================================================+ +// | LLInvFVBridge | +// +=================================================+ + +LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) : +mUUID(uuid), mInvType(LLInventoryType::IT_NONE) +{ + mInventoryPanel = inventory->getHandle(); +} + +const std::string& LLInvFVBridge::getName() const +{ + LLInventoryObject* obj = getInventoryObject(); + if(obj) + { + return obj->getName(); + } + return LLStringUtil::null; +} + +const std::string& LLInvFVBridge::getDisplayName() const +{ + return getName(); +} + +// Folders have full perms +PermissionMask LLInvFVBridge::getPermissionMask() const +{ + + return PERM_ALL; +} + +// virtual +LLAssetType::EType LLInvFVBridge::getPreferredType() const +{ + return LLAssetType::AT_NONE; +} + + +// Folders don't have creation dates. +time_t LLInvFVBridge::getCreationDate() const +{ + return 0; +} + +// Can be destoryed (or moved to trash) +BOOL LLInvFVBridge::isItemRemovable() +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) + { + return TRUE; + } + return FALSE; +} + +// Sends an update to all link items that point to the base item. +void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string& new_name) +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + + LLInventoryItem* itemp = model->getItem(mUUID); + if (!itemp) return; + + if (itemp->getIsLinkType()) + { + return; + } + + LLInventoryModel::item_array_t item_array = model->collectLinkedItems(item_id); + for (LLInventoryModel::item_array_t::iterator iter = item_array.begin(); + iter != item_array.end(); + iter++) + { + LLViewerInventoryItem *linked_item = (*iter); + if (linked_item->getUUID() == item_id) continue; + + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item); + new_item->rename(new_name); + new_item->updateServer(FALSE); + model->updateItem(new_item); + // model->addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID()); + } + model->notifyObservers(); +} + +// Can be moved to another folder +BOOL LLInvFVBridge::isItemMovable() const +{ + return TRUE; +} + +/*virtual*/ +/** + * @brief Adds this item into clipboard storage + */ +void LLInvFVBridge::cutToClipboard() +{ + if(isItemMovable()) + { + LLInventoryClipboard::instance().cut(mUUID); + } +} +// *TODO: make sure this does the right thing +void LLInvFVBridge::showProperties() +{ + LLSD key; + key["id"] = mUUID; + LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); + + // LLFloaterReg::showInstance("properties", mUUID); +} + +void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) +{ + // Deactivate gestures when moving them into Trash + LLInvFVBridge* bridge; + LLInventoryModel* model = getInventoryModel(); + LLViewerInventoryItem* item = NULL; + LLViewerInventoryCategory* cat = NULL; + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + S32 count = batch.count(); + S32 i,j; + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); + if (item) + { + if(LLAssetType::AT_GESTURE == item->getType()) + { + LLGestureManager::instance().deactivateGesture(item->getUUID()); + } + } + } + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); + if (cat) + { + gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE ); + for (j=0; j<descendent_items.count(); j++) + { + if(LLAssetType::AT_GESTURE == descendent_items[j]->getType()) + { + LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID()); + } + } + } + } + removeBatchNoCheck(batch); +} + +void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch) +{ + // this method moves a bunch of items and folders to the trash. As + // per design guidelines for the inventory model, the message is + // built and the accounting is performed first. After all of that, + // we call LLInventoryModel::moveObject() to move everything + // around. + LLInvFVBridge* bridge; + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLMessageSystem* msg = gMessageSystem; + LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + LLViewerInventoryItem* item = NULL; + LLViewerInventoryCategory* cat = NULL; + std::vector<LLUUID> move_ids; + LLInventoryModel::update_map_t update; + bool start_new_message = true; + S32 count = batch.count(); + S32 i; + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); + if(item) + { + if(item->getParentUUID() == trash_id) continue; + move_ids.push_back(item->getUUID()); + LLPreview::hide(item->getUUID()); + --update[item->getParentUUID()]; + ++update[trash_id]; + if(start_new_message) + { + start_new_message = false; + msg->newMessageFast(_PREHASH_MoveInventoryItem); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addBOOLFast(_PREHASH_Stamp, TRUE); + } + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_ItemID, item->getUUID()); + msg->addUUIDFast(_PREHASH_FolderID, trash_id); + msg->addString("NewName", NULL); + if(msg->isSendFullFast(_PREHASH_InventoryData)) + { + start_new_message = true; + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + update.clear(); + } + } + } + if(!start_new_message) + { + start_new_message = true; + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + update.clear(); + } + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); + if(cat) + { + if(cat->getParentUUID() == trash_id) continue; + move_ids.push_back(cat->getUUID()); + --update[cat->getParentUUID()]; + ++update[trash_id]; + if(start_new_message) + { + start_new_message = false; + msg->newMessageFast(_PREHASH_MoveInventoryFolder); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addBOOL("Stamp", TRUE); + } + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID()); + msg->addUUIDFast(_PREHASH_ParentID, trash_id); + if(msg->isSendFullFast(_PREHASH_InventoryData)) + { + start_new_message = true; + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + update.clear(); + } + } + } + if(!start_new_message) + { + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + } + + // move everything. + std::vector<LLUUID>::iterator it = move_ids.begin(); + std::vector<LLUUID>::iterator end = move_ids.end(); + for(; it != end; ++it) + { + gInventory.moveObject((*it), trash_id); + } + + // notify inventory observers. + model->notifyObservers(); +} + +BOOL LLInvFVBridge::isClipboardPasteable() const +{ + if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) + { + return FALSE; + } + LLInventoryModel* model = getInventoryModel(); + if (!model) + { + return FALSE; + } + + const LLUUID &agent_id = gAgent.getID(); + + LLDynamicArray<LLUUID> objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + for(S32 i = 0; i < count; i++) + { + const LLUUID &item_id = objects.get(i); + + // Can't paste folders + const LLInventoryCategory *cat = model->getCategory(item_id); + if (cat) + { + return FALSE; + } + + const LLInventoryItem *item = model->getItem(item_id); + if (item) + { + if (!item->getPermissions().allowCopyBy(agent_id)) + { + return FALSE; + } + } + } + return TRUE; +} + +BOOL LLInvFVBridge::isClipboardPasteableAsLink() const +{ + if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) + { + return FALSE; + } + const LLInventoryModel* model = getInventoryModel(); + if (!model) + { + return FALSE; + } + + LLDynamicArray<LLUUID> objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + for(S32 i = 0; i < count; i++) + { + const LLInventoryItem *item = model->getItem(objects.get(i)); + if (item) + { + if (!LLAssetType::lookupCanLink(item->getActualType())) + { + return FALSE; + } + } + const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i)); + if (cat && !LLAssetType::lookupCanLink(cat->getPreferredType())) + { + return FALSE; + } + } + return TRUE; +} + +void hide_context_entries(LLMenuGL& menu, + const std::vector<std::string> &entries_to_show, + const std::vector<std::string> &disabled_entries) +{ + const LLView::child_list_t *list = menu.getChildList(); + + LLView::child_list_t::const_iterator itor; + for (itor = list->begin(); itor != list->end(); ++itor) + { + std::string name = (*itor)->getName(); + + // descend into split menus: + LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor); + if ((name == "More") && branchp) + { + hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries); + } + + + bool found = false; + std::vector<std::string>::const_iterator itor2; + for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2) + { + if (*itor2 == name) + { + found = true; + } + } + if (!found) + { + (*itor)->setVisible(FALSE); + } + else + { + for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) + { + if (*itor2 == name) + { + (*itor)->setEnabled(FALSE); + } + } + } + } +} + +// Helper for commonly-used entries +void LLInvFVBridge::getClipboardEntries(bool show_asset_id, + std::vector<std::string> &items, + std::vector<std::string> &disabled_items, U32 flags) +{ + items.push_back(std::string("Rename")); + if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Rename")); + } + + if (show_asset_id) + { + items.push_back(std::string("Copy Asset UUID")); + if ( (! ( isItemPermissive() || gAgent.isGodlike() ) ) + || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Copy Asset UUID")); + } + } + + items.push_back(std::string("Copy Separator")); + + items.push_back(std::string("Copy")); + if (!isItemCopyable()) + { + disabled_items.push_back(std::string("Copy")); + } + + items.push_back(std::string("Paste")); + if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Paste")); + } + + items.push_back(std::string("Paste As Link")); + if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Paste As Link")); + } + items.push_back(std::string("Paste Separator")); + + items.push_back(std::string("Delete")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Delete")); + } +} + +void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl; + std::vector<std::string> items; + std::vector<std::string> disabled_items; + if(isInTrash()) + { + items.push_back(std::string("PurgeItem")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("PurgeItem")); + } + items.push_back(std::string("RestoreItem")); + } + else + { + items.push_back(std::string("Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + } + hide_context_entries(menu, items, disabled_items); +} + +// *TODO: remove this +BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const +{ + BOOL rv = FALSE; + + const LLInventoryObject* obj = getInventoryObject(); + + if(obj) + { + *type = LLAssetType::lookupDragAndDropType(obj->getActualType()); + if(*type == DAD_NONE) + { + return FALSE; + } + + *id = obj->getUUID(); + //object_ids.put(obj->getUUID()); + + if (*type == DAD_CATEGORY) + { + gInventory.startBackgroundFetch(obj->getUUID()); + } + + rv = TRUE; + } + + return rv; +} + +LLInventoryObject* LLInvFVBridge::getInventoryObject() const +{ + LLInventoryObject* obj = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + obj = (LLInventoryObject*)model->getObject(mUUID); + } + return obj; +} + +LLInventoryModel* LLInvFVBridge::getInventoryModel() const +{ + LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + return panel ? panel->getModel() : NULL; +} + +BOOL LLInvFVBridge::isInTrash() const +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + return model->isObjectDescendentOf(mUUID, trash_id); +} + +BOOL LLInvFVBridge::isLinkedObjectInTrash() const +{ + if (isInTrash()) return TRUE; + + const LLInventoryObject *obj = getInventoryObject(); + if (obj && obj->getIsLinkType()) + { + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id); + } + return FALSE; +} + +BOOL LLInvFVBridge::isAgentInventory() const +{ + const LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + if(gInventory.getRootFolderID() == mUUID) return TRUE; + return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); +} + +BOOL LLInvFVBridge::isCOFFolder() const +{ + const LLInventoryModel* model = getInventoryModel(); + if(!model) return TRUE; + const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); + if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id)) + { + return TRUE; + } + return FALSE; +} + +BOOL LLInvFVBridge::isItemPermissive() const +{ + return FALSE; +} + +// static +void LLInvFVBridge::changeItemParent(LLInventoryModel* model, + LLViewerInventoryItem* item, + const LLUUID& new_parent, + BOOL restamp) +{ + if(item->getParentUUID() != new_parent) + { + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); + update.push_back(new_folder); + gInventory.accountForUpdate(update); + + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); + new_item->setParent(new_parent); + new_item->updateParentOnServer(restamp); + model->updateItem(new_item); + model->notifyObservers(); + } +} + +// static +void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model, + LLViewerInventoryCategory* cat, + const LLUUID& new_parent, + BOOL restamp) +{ + if(cat->getParentUUID() != new_parent) + { + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); + update.push_back(new_folder); + gInventory.accountForUpdate(update); + + LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat); + new_cat->setParent(new_parent); + new_cat->updateParentOnServer(restamp); + model->updateCategory(new_cat); + model->notifyObservers(); + } +} + + +const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type) +{ + const std::string rv= LLInventoryType::lookup(inv_type); + if(rv.empty()) + { + return std::string("<invalid>"); + } + return rv; +} + +LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, + LLAssetType::EType actual_asset_type, + LLInventoryType::EType inv_type, + LLInventoryPanel* inventory, + const LLUUID& uuid, + U32 flags) +{ + LLInvFVBridge* new_listener = NULL; + switch(asset_type) + { + case LLAssetType::AT_TEXTURE: + if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLTextureBridge(inventory, uuid, inv_type); + break; + + case LLAssetType::AT_SOUND: + if(!(inv_type == LLInventoryType::IT_SOUND)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLSoundBridge(inventory, uuid); + break; + + case LLAssetType::AT_LANDMARK: + if(!(inv_type == LLInventoryType::IT_LANDMARK)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLLandmarkBridge(inventory, uuid, flags); + break; + + case LLAssetType::AT_CALLINGCARD: + if(!(inv_type == LLInventoryType::IT_CALLINGCARD)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLCallingCardBridge(inventory, uuid); + break; + + case LLAssetType::AT_SCRIPT: + if(!(inv_type == LLInventoryType::IT_LSL)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLScriptBridge(inventory, uuid); + break; + + case LLAssetType::AT_OBJECT: + if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags); + break; + + case LLAssetType::AT_NOTECARD: + if(!(inv_type == LLInventoryType::IT_NOTECARD)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLNotecardBridge(inventory, uuid); + break; + + case LLAssetType::AT_ANIMATION: + if(!(inv_type == LLInventoryType::IT_ANIMATION)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLAnimationBridge(inventory, uuid); + break; + + case LLAssetType::AT_GESTURE: + if(!(inv_type == LLInventoryType::IT_GESTURE)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLGestureBridge(inventory, uuid); + break; + + case LLAssetType::AT_LSL_TEXT: + if(!(inv_type == LLInventoryType::IT_LSL)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLLSLTextBridge(inventory, uuid); + break; + + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + if(!(inv_type == LLInventoryType::IT_WEARABLE)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags); + break; + case LLAssetType::AT_CATEGORY: + case LLAssetType::AT_ROOT_CATEGORY: + if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) + { + // Create a link folder handler instead. + new_listener = new LLLinkFolderBridge(inventory, uuid); + break; + } + new_listener = new LLFolderBridge(inventory, uuid); + break; + case LLAssetType::AT_LINK: + // Only should happen for broken links. + new_listener = new LLLinkItemBridge(inventory, uuid); + break; + case LLAssetType::AT_LINK_FOLDER: + // Only should happen for broken links. + new_listener = new LLLinkItemBridge(inventory, uuid); + break; + default: + llinfos << "Unhandled asset type (llassetstorage.h): " + << (S32)asset_type << llendl; + break; + } + + if (new_listener) + { + new_listener->mInvType = inv_type; + } + + return new_listener; +} + +void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) +{ + LLInventoryCategory* cat = model->getCategory(uuid); + if (cat) + { + model->purgeDescendentsOf(uuid); + model->notifyObservers(); + } + LLInventoryObject* obj = model->getObject(uuid); + if (obj) + { + model->purgeObject(uuid); + model->notifyObservers(); + } +} + +// +=================================================+ +// | InventoryFVBridgeBuilder | +// +=================================================+ +LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type, + LLAssetType::EType actual_asset_type, + LLInventoryType::EType inv_type, + LLInventoryPanel* inventory, + const LLUUID& uuid, + U32 flags /* = 0x00 */) const +{ + return LLInvFVBridge::createBridge(asset_type, + actual_asset_type, + inv_type, + inventory, + uuid, + flags); +} + +// +=================================================+ +// | LLItemBridge | +// +=================================================+ + +void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("goto" == action) + { + gotoItem(folder); + } + if ("open" == action) + { + openItem(); + return; + } + else if ("properties" == action) + { + showProperties(); + return; + } + else if ("purge" == action) + { + purgeItem(model, mUUID); + return; + } + else if ("restoreToWorld" == action) + { + restoreToWorld(); + return; + } + else if ("restore" == action) + { + restoreItem(); + return; + } + else if ("copy_uuid" == action) + { + // Single item only + LLInventoryItem* item = model->getItem(mUUID); + if(!item) return; + LLUUID asset_id = item->getAssetUUID(); + std::string buffer; + asset_id.toString(buffer); + + gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer)); + return; + } + else if ("copy" == action) + { + copyToClipboard(); + return; + } + else if ("paste" == action) + { + // Single item only + LLInventoryItem* itemp = model->getItem(mUUID); + if (!itemp) return; + + LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID()); + if (!folder_view_itemp) return; + + folder_view_itemp->getListener()->pasteFromClipboard(); + return; + } + else if ("paste_link" == action) + { + // Single item only + LLInventoryItem* itemp = model->getItem(mUUID); + if (!itemp) return; + + LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID()); + if (!folder_view_itemp) return; + + folder_view_itemp->getListener()->pasteLinkFromClipboard(); + return; + } +} + +void LLItemBridge::selectItem() +{ + LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); + if(item && !item->isComplete()) + { + item->fetchFromServer(); + } +} + +void LLItemBridge::restoreItem() +{ + LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); + if(item) + { + LLInventoryModel* model = getInventoryModel(); + const LLUUID new_parent = model->findCategoryUUIDForType(item->getType()); + // do not restamp on restore. + LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE); + } +} + +void LLItemBridge::restoreToWorld() +{ + LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)getItem(); + if (itemp) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("RezRestoreToWorld"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_InventoryData); + itemp->packMessage(msg); + msg->sendReliable(gAgent.getRegion()->getHost()); + } + + //Similar functionality to the drag and drop rez logic + BOOL remove_from_inventory = FALSE; + + //remove local inventory copy, sim will deal with permissions and removing the item + //from the actual inventory if its a no-copy etc + if(!itemp->getPermissions().allowCopyBy(gAgent.getID())) + { + remove_from_inventory = TRUE; + } + + // Check if it's in the trash. (again similar to the normal rez logic) + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id)) + { + remove_from_inventory = TRUE; + } + + if(remove_from_inventory) + { + gInventory.deleteObject(itemp->getUUID()); + gInventory.notifyObservers(); + } +} + +void LLItemBridge::gotoItem(LLFolderView *folder) +{ + LLInventoryObject *obj = getInventoryObject(); + if (obj && obj->getIsLinkType()) + { + LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); + if (active_panel) + { + active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO); + } + } +} + +LLUIImagePtr LLItemBridge::getIcon() const +{ + return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]); +} + +PermissionMask LLItemBridge::getPermissionMask() const +{ + LLViewerInventoryItem* item = getItem(); + PermissionMask perm_mask = 0; + if(item) + { + BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); + BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); + BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID()); + + if (copy) perm_mask |= PERM_COPY; + if (mod) perm_mask |= PERM_MODIFY; + if (xfer) perm_mask |= PERM_TRANSFER; + + } + return perm_mask; +} + +const std::string& LLItemBridge::getDisplayName() const +{ + if(mDisplayName.empty()) + { + buildDisplayName(getItem(), mDisplayName); + } + return mDisplayName; +} + +void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) +{ + if(item) + { + name.assign(item->getName()); + } + else + { + name.assign(LLStringUtil::null); + } +} + +LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const +{ + U8 font = LLFontGL::NORMAL; + + if( gAgentWearables.isWearingItem( mUUID ) ) + { + // llinfos << "BOLD" << llendl; + font |= LLFontGL::BOLD; + } + + const LLViewerInventoryItem* item = getItem(); + if (item && item->getIsLinkType()) + { + font |= LLFontGL::ITALIC; + } + return (LLFontGL::StyleFlags)font; +} + +std::string LLItemBridge::getLabelSuffix() const +{ + // String table is loaded before login screen and inventory items are + // loaded after login, so LLTrans should be ready. + static std::string NO_COPY =LLTrans::getString("no_copy"); + static std::string NO_MOD = LLTrans::getString("no_modify"); + static std::string NO_XFER = LLTrans::getString("no_transfer"); + static std::string LINK = LLTrans::getString("link"); + static std::string BROKEN_LINK = LLTrans::getString("broken_link"); + std::string suffix; + LLInventoryItem* item = getItem(); + if(item) + { + // it's a bit confusing to put nocopy/nomod/etc on calling cards. + if(LLAssetType::AT_CALLINGCARD != item->getType() + && item->getPermissions().getOwner() == gAgent.getID()) + { + BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType()); + if (broken_link) return BROKEN_LINK; + + BOOL link = item->getIsLinkType(); + if (link) return LINK; + + BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); + if (!copy) + { + suffix += NO_COPY; + } + BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); + if (!mod) + { + suffix += NO_MOD; + } + BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID()); + if (!xfer) + { + suffix += NO_XFER; + } + } + } + return suffix; +} + +time_t LLItemBridge::getCreationDate() const +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + return item->getCreationDate(); + } + return 0; +} + + +BOOL LLItemBridge::isItemRenameable() const +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + // (For now) Don't allow calling card rename since that may confuse users as to + // what the calling card points to. + if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD) + { + return FALSE; + } + return (item->getPermissions().allowModifyBy(gAgent.getID())); + } + return FALSE; +} + +BOOL LLItemBridge::renameItem(const std::string& new_name) +{ + if(!isItemRenameable()) + return FALSE; + LLPreview::dirty(mUUID); + LLInventoryModel* model = getInventoryModel(); + if(!model) + return FALSE; + LLViewerInventoryItem* item = getItem(); + if(item && (item->getName() != new_name)) + { + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); + new_item->rename(new_name); + buildDisplayName(new_item, mDisplayName); + new_item->updateServer(FALSE); + model->updateItem(new_item); + + model->notifyObservers(); + } + // return FALSE because we either notified observers (& therefore + // rebuilt) or we didn't update. + return FALSE; +} + + +BOOL LLItemBridge::removeItem() +{ + if(!isItemRemovable()) + { + return FALSE; + } + // move it to the trash + LLPreview::hide(mUUID, TRUE); + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + LLViewerInventoryItem* item = getItem(); + + // if item is not already in trash + if(item && !model->isObjectDescendentOf(mUUID, trash_id)) + { + // move to trash, and restamp + LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE); + // delete was successful + return TRUE; + } + else + { + // tried to delete already item in trash (should purge?) + return FALSE; + } +} + +BOOL LLItemBridge::isItemCopyable() const +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + // can't copy worn objects. DEV-15183 + LLVOAvatarSelf *avatarp = gAgent.getAvatarObject(); + if( !avatarp ) + { + return FALSE; + } + + if(avatarp->isWearingAttachment(mUUID)) + { + return FALSE; + } + + // All items can be copied, not all can be pasted. + // The only time an item can't be copied is if it's a link + // return (item->getPermissions().allowCopyBy(gAgent.getID())); + if (item->getIsLinkType()) + { + return FALSE; + } + return TRUE; + } + return FALSE; +} +BOOL LLItemBridge::copyToClipboard() const +{ + if(isItemCopyable()) + { + LLInventoryClipboard::instance().add(mUUID); + return TRUE; + } + return FALSE; +} + +LLViewerInventoryItem* LLItemBridge::getItem() const +{ + LLViewerInventoryItem* item = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + item = (LLViewerInventoryItem*)model->getItem(mUUID); + } + return item; +} + +BOOL LLItemBridge::isItemPermissive() const +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + U32 mask = item->getPermissions().getMaskBase(); + if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) + { + return TRUE; + } + } + return FALSE; +} + +// +=================================================+ +// | LLFolderBridge | +// +=================================================+ + +LLFolderBridge* LLFolderBridge::sSelf=NULL; + +// Can be moved to another folder +BOOL LLFolderBridge::isItemMovable() const +{ + LLInventoryObject* obj = getInventoryObject(); + if(obj) + { + return (!LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)obj)->getPreferredType())); + } + return FALSE; +} + +void LLFolderBridge::selectItem() +{ +} + + +// Can be destroyed (or moved to trash) +BOOL LLFolderBridge::isItemRemovable() +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) + { + return FALSE; + } + + if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) + { + return FALSE; + } + + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if( !avatar ) + { + return FALSE; + } + + LLInventoryCategory* category = model->getCategory(mUUID); + if( !category ) + { + return FALSE; + } + + if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType())) + { + return FALSE; + } + + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE ); + + S32 i; + for( i = 0; i < descendent_categories.count(); i++ ) + { + LLInventoryCategory* category = descendent_categories[i]; + if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType())) + { + return FALSE; + } + } + + for( i = 0; i < descendent_items.count(); i++ ) + { + LLInventoryItem* item = descendent_items[i]; + if( (item->getType() == LLAssetType::AT_CLOTHING) || + (item->getType() == LLAssetType::AT_BODYPART) ) + { + if(gAgentWearables.isWearingItem(item->getUUID())) + { + return FALSE; + } + } + else + if( item->getType() == LLAssetType::AT_OBJECT ) + { + if(avatar->isWearingAttachment(item->getUUID())) + { + return FALSE; + } + } + } + + return TRUE; +} + +BOOL LLFolderBridge::isUpToDate() const +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); + if( !category ) + { + return FALSE; + } + + return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN; +} + +BOOL LLFolderBridge::isItemCopyable() const +{ + return TRUE; +} + +BOOL LLFolderBridge::copyToClipboard() const +{ + if(isItemCopyable()) + { + LLInventoryClipboard::instance().add(mUUID); + return TRUE; + } + return FALSE; +} + +BOOL LLFolderBridge::isClipboardPasteable() const +{ + if ( ! LLInvFVBridge::isClipboardPasteable() ) + return FALSE; + + // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 + if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) ) + { + LLInventoryModel* model = getInventoryModel(); + if ( !model ) + { + return FALSE; + } + + LLDynamicArray<LLUUID> objects; + LLInventoryClipboard::instance().retrieve(objects); + const LLViewerInventoryCategory *current_cat = getCategory(); + + // Search for the direct descendent of current Friends subfolder among all pasted items, + // and return false if is found. + for(S32 i = objects.count() - 1; i >= 0; --i) + { + const LLUUID &obj_id = objects.get(i); + if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) + { + return FALSE; + } + } + + } + return TRUE; +} + +BOOL LLFolderBridge::isClipboardPasteableAsLink() const +{ + // Check normal paste-as-link permissions + if (!LLInvFVBridge::isClipboardPasteableAsLink()) + { + return FALSE; + } + + const LLInventoryModel* model = getInventoryModel(); + if (!model) + { + return FALSE; + } + + const LLViewerInventoryCategory *current_cat = getCategory(); + if (current_cat) + { + const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat ); + const LLUUID ¤t_cat_id = current_cat->getUUID(); + LLDynamicArray<LLUUID> objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + for(S32 i = 0; i < count; i++) + { + const LLUUID &obj_id = objects.get(i); + const LLInventoryCategory *cat = model->getCategory(obj_id); + if (cat) + { + const LLUUID &cat_id = cat->getUUID(); + // Don't allow recursive pasting + if ((cat_id == current_cat_id) || + model->isObjectDescendentOf(current_cat_id, cat_id)) + { + return FALSE; + } + } + // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 + if ( is_in_friend_folder ) + { + // If object is direct descendent of current Friends subfolder than return false. + // Note: We can't use 'const LLInventoryCategory *cat', because it may be null + // in case type of obj_id is LLInventoryItem. + if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) + { + return FALSE; + } + } + } + } + return TRUE; + +} + +BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, + BOOL drop) +{ + // This should never happen, but if an inventory item is incorrectly parented, + // the UI will get confused and pass in a NULL. + if(!inv_cat) return FALSE; + + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if(!avatar) return FALSE; + + // cannot drag categories into library + if(!isAgentInventory()) + { + return FALSE; + } + + // check to make sure source is agent inventory, and is represented there. + LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); + BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL) + && (LLToolDragAndDrop::SOURCE_AGENT == source); + + BOOL accept = FALSE; + S32 i; + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + if(is_agent_inventory) + { + const LLUUID& cat_id = inv_cat->getUUID(); + + // Is the destination the trash? + const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + BOOL move_is_into_trash = (mUUID == trash_id) + || model->isObjectDescendentOf(mUUID, trash_id); + BOOL is_movable = (!LLAssetType::lookupIsProtectedCategoryType(inv_cat->getPreferredType())); + LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); + BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT); + if (move_is_into_current_outfit || move_is_into_outfit) + { + // BAP - restrictions? + is_movable = true; + } + + if (mUUID == gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE)) + { + is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604 + } + + if( is_movable ) + { + gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE ); + + for( i = 0; i < descendent_categories.count(); i++ ) + { + LLInventoryCategory* category = descendent_categories[i]; + if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType())) + { + // ...can't move "special folders" like Textures + is_movable = FALSE; + break; + } + } + + if( is_movable ) + { + if( move_is_into_trash ) + { + for( i = 0; i < descendent_items.count(); i++ ) + { + LLInventoryItem* item = descendent_items[i]; + if( (item->getType() == LLAssetType::AT_CLOTHING) || + (item->getType() == LLAssetType::AT_BODYPART) ) + { + if( gAgentWearables.isWearingItem( item->getUUID() ) ) + { + is_movable = FALSE; // It's generally movable, but not into the trash! + break; + } + } + else + if( item->getType() == LLAssetType::AT_OBJECT ) + { + if( avatar->isWearingAttachment( item->getUUID() ) ) + { + is_movable = FALSE; // It's generally movable, but not into the trash! + break; + } + } + } + } + } + } + + + accept = is_movable + && (mUUID != cat_id) // Can't move a folder into itself + && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing + && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity + if(accept && drop) + { + // Look for any gestures and deactivate them + if (move_is_into_trash) + { + for (i = 0; i < descendent_items.count(); i++) + { + LLInventoryItem* item = descendent_items[i]; + if (item->getType() == LLAssetType::AT_GESTURE + && LLGestureManager::instance().isGestureActive(item->getUUID())) + { + LLGestureManager::instance().deactivateGesture(item->getUUID()); + } + } + } + // if target is an outfit or current outfit folder we use link + if (move_is_into_current_outfit || move_is_into_outfit) + { +#if SUPPORT_ENSEMBLES + // BAP - should skip if dup. + if (move_is_into_current_outfit) + { + LLAppearanceManager::wearEnsemble(inv_cat); + } + else + { + LLPointer<LLInventoryCallback> cb = NULL; + link_inventory_item( + gAgent.getID(), + inv_cat->getUUID(), + mUUID, + inv_cat->getName(), + LLAssetType::AT_LINK_FOLDER, + cb); + } +#endif + } + else + { + + // Reparent the folder and restamp children if it's moving + // into trash. + LLInvFVBridge::changeCategoryParent( + model, + (LLViewerInventoryCategory*)inv_cat, + mUUID, + move_is_into_trash); + } + } + } + else if(LLToolDragAndDrop::SOURCE_WORLD == source) + { + // content category has same ID as object itself + LLUUID object_id = inv_cat->getUUID(); + LLUUID category_id = mUUID; + accept = move_inv_category_world_to_agent(object_id, category_id, drop); + } + return accept; +} + +void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv) +{ + const char* dialog = NULL; + if (object->flagScripted()) + { + dialog = "MoveInventoryFromScriptedObject"; + } + else + { + dialog = "MoveInventoryFromObject"; + } + LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv)); +} + +// Move/copy all inventory items from the Contents folder of an in-world +// object to the agent's inventory, inside a given category. +BOOL move_inv_category_world_to_agent(const LLUUID& object_id, + const LLUUID& category_id, + BOOL drop, + void (*callback)(S32, void*), + void* user_data) +{ + // Make sure the object exists. If we allowed dragging from + // anonymous objects, it would be possible to bypass + // permissions. + // content category has same ID as object itself + LLViewerObject* object = gObjectList.findObject(object_id); + if(!object) + { + llinfos << "Object not found for drop." << llendl; + return FALSE; + } + + // this folder is coming from an object, as there is only one folder in an object, the root, + // we need to collect the entire contents and handle them as a group + InventoryObjectList inventory_objects; + object->getInventoryContents(inventory_objects); + + if (inventory_objects.empty()) + { + llinfos << "Object contents not found for drop." << llendl; + return FALSE; + } + + BOOL accept = TRUE; + BOOL is_move = FALSE; + + // coming from a task. Need to figure out if the person can + // move/copy this item. + InventoryObjectList::iterator it = inventory_objects.begin(); + InventoryObjectList::iterator end = inventory_objects.end(); + for ( ; it != end; ++it) + { + // coming from a task. Need to figure out if the person can + // move/copy this item. + LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions()); + if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) + && perm.allowTransferTo(gAgent.getID()))) +// || gAgent.isGodlike()) + { + accept = TRUE; + } + else if(object->permYouOwner()) + { + // If the object cannot be copied, but the object the + // inventory is owned by the agent, then the item can be + // moved from the task to agent inventory. + is_move = TRUE; + accept = TRUE; + } + else + { + accept = FALSE; + break; + } + } + + if(drop && accept) + { + it = inventory_objects.begin(); + InventoryObjectList::iterator first_it = inventory_objects.begin(); + LLMoveInv* move_inv = new LLMoveInv; + move_inv->mObjectID = object_id; + move_inv->mCategoryID = category_id; + move_inv->mCallback = callback; + move_inv->mUserData = user_data; + + for ( ; it != end; ++it) + { + two_uuids_t two(category_id, (*it)->getUUID()); + move_inv->mMoveList.push_back(two); + } + + if(is_move) + { + // Callback called from within here. + warn_move_inventory(object, move_inv); + } + else + { + LLNotification::Params params("MoveInventoryFromObject"); + params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); + LLNotifications::instance().forceResponse(params, 0); + } + } + return accept; +} + +bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat, + LLInventoryItem* item) +{ + // Valid COF items are: + // - links to wearables (body parts or clothing) + // - links to attachments + // - links to gestures + // - links to ensemble folders + LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); // BAP - safe? + if (linked_item) + { + LLAssetType::EType type = linked_item->getType(); + return (type == LLAssetType::AT_CLOTHING || + type == LLAssetType::AT_BODYPART || + type == LLAssetType::AT_GESTURE || + type == LLAssetType::AT_OBJECT); + } + else + { + LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe? + // BAP remove AT_NONE support after ensembles are fully working? + return (linked_category && + ((linked_category->getPreferredType() == LLAssetType::AT_NONE) || + (LLAssetType::lookupIsEnsembleCategoryType(linked_category->getPreferredType())))); + } +} + + +bool LLFindWearables::operator()(LLInventoryCategory* cat, + LLInventoryItem* item) +{ + if(item) + { + if((item->getType() == LLAssetType::AT_CLOTHING) + || (item->getType() == LLAssetType::AT_BODYPART)) + { + return TRUE; + } + } + return FALSE; +} + + + +//Used by LLFolderBridge as callback for directory recursion. +class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver +{ +public: + LLRightClickInventoryFetchObserver() : + mCopyItems(false) + { }; + LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) : + mCatID(cat_id), + mCopyItems(copy_items) + { }; + virtual void done() + { + // we've downloaded all the items, so repaint the dialog + LLFolderBridge::staticFolderOptionsMenu(); + + gInventory.removeObserver(this); + delete this; + } + + +protected: + LLUUID mCatID; + bool mCopyItems; + +}; + +//Used by LLFolderBridge as callback for directory recursion. +class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver +{ +public: + LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {} + ~LLRightClickInventoryFetchDescendentsObserver() {} + virtual void done(); +protected: + bool mCopyItems; +}; + +void LLRightClickInventoryFetchDescendentsObserver::done() +{ + // Avoid passing a NULL-ref as mCompleteFolders.front() down to + // gInventory.collectDescendents() + if( mCompleteFolders.empty() ) + { + llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl; + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + return; + } + + // What we do here is get the complete information on the items in + // the library, and set up an observer that will wait for that to + // happen. + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(mCompleteFolders.front(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + S32 count = item_array.count(); +#if 0 // HACK/TODO: Why? + // This early causes a giant menu to get produced, and doesn't seem to be needed. + if(!count) + { + llwarns << "Nothing fetched in category " << mCompleteFolders.front() + << llendl; + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + return; + } +#endif + + LLRightClickInventoryFetchObserver* outfit; + outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems); + LLInventoryFetchObserver::item_ref_t ids; + for(S32 i = 0; i < count; ++i) + { + ids.push_back(item_array.get(i)->getUUID()); + } + + // clean up, and remove this as an observer since the call to the + // outfit could notify observers and throw us into an infinite + // loop. + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + + // increment busy count and either tell the inventory to check & + // call done, or add this object to the inventory for observation. + inc_busy_count(); + + // do the fetch + outfit->fetchItems(ids); + outfit->done(); //Not interested in waiting and this will be right 99% of the time. +//Uncomment the following code for laggy Inventory UI. +/* if(outfit->isEverythingComplete()) + { + // everything is already here - call done. + outfit->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(outfit); + }*/ +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryWearObserver +// +// Observer for "copy and wear" operation to support knowing +// when the all of the contents have been added to inventory. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLInventoryCopyAndWearObserver : public LLInventoryObserver +{ +public: + LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {} + virtual ~LLInventoryCopyAndWearObserver() {} + virtual void changed(U32 mask); + +protected: + LLUUID mCatID; + int mContentsCount; + BOOL mFolderAdded; +}; + + + +void LLInventoryCopyAndWearObserver::changed(U32 mask) +{ + if((mask & (LLInventoryObserver::ADD)) != 0) + { + if (!mFolderAdded) + { + const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); + + std::set<LLUUID>::const_iterator id_it = changed_items.begin(); + std::set<LLUUID>::const_iterator id_end = changed_items.end(); + for (;id_it != id_end; ++id_it) + { + if ((*id_it) == mCatID) + { + mFolderAdded = TRUE; + break; + } + } + } + + if (mFolderAdded) + { + LLViewerInventoryCategory* category = gInventory.getCategory(mCatID); + + if (NULL == category) + { + llwarns << "gInventory.getCategory(" << mCatID + << ") was NULL" << llendl; + } + else + { + if (category->getDescendentCount() == + mContentsCount) + { + gInventory.removeObserver(this); + LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE); + delete this; + } + } + } + + } +} + + + +void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("open" == action) + { + openItem(); + return; + } + else if ("paste" == action) + { + pasteFromClipboard(); + return; + } + else if ("paste_link" == action) + { + pasteLinkFromClipboard(); + return; + } + else if ("properties" == action) + { + showProperties(); + return; + } + else if ("replaceoutfit" == action) + { + modifyOutfit(FALSE); + return; + } +#if SUPPORT_ENSEMBLES + else if ("wearasensemble" == action) + { + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLViewerInventoryCategory* cat = getCategory(); + if(!cat) return; + LLAppearanceManager::wearEnsemble(cat,true); + return; + } +#endif + else if ("addtooutfit" == action) + { + modifyOutfit(TRUE); + return; + } + else if ("copy" == action) + { + copyToClipboard(); + return; + } + else if ("removefromoutfit" == action) + { + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLViewerInventoryCategory* cat = getCategory(); + if(!cat) return; + + remove_inventory_category_from_avatar ( cat ); + return; + } + else if ("purge" == action) + { + purgeItem(model, mUUID); + return; + } + else if ("restore" == action) + { + restoreItem(); + return; + } +} + +void LLFolderBridge::openItem() +{ + lldebugs << "LLFolderBridge::openItem()" << llendl; + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + bool fetching_inventory = model->fetchDescendentsOf(mUUID); + // Only change folder type if we have the folder contents. + if (!fetching_inventory) + { + // Disabling this for now, it's causing crash when new items are added to folders + // since folder type may change before new item item has finished processing. + // determineFolderType(); + } +} + +void LLFolderBridge::closeItem() +{ + determineFolderType(); +} + +void LLFolderBridge::determineFolderType() +{ + if (isUpToDate()) + { + LLInventoryModel* model = getInventoryModel(); + LLViewerInventoryCategory* category = model->getCategory(mUUID); + category->determineFolderType(); + } +} + +BOOL LLFolderBridge::isItemRenameable() const +{ + LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory(); + if(cat && !LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()) + && (cat->getOwnerID() == gAgent.getID())) + { + return TRUE; + } + return FALSE; +} + +void LLFolderBridge::restoreItem() +{ + LLViewerInventoryCategory* cat; + cat = (LLViewerInventoryCategory*)getCategory(); + if(cat) + { + LLInventoryModel* model = getInventoryModel(); + LLUUID new_parent = model->findCategoryUUIDForType(cat->getType()); + // do not restamp children on restore + LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE); + } +} + +LLAssetType::EType LLFolderBridge::getPreferredType() const +{ + LLAssetType::EType preferred_type = LLAssetType::AT_NONE; + LLViewerInventoryCategory* cat = getCategory(); + if(cat) + { + preferred_type = cat->getPreferredType(); + } + + return preferred_type; +} + +// Icons for folders are based on the preferred type +LLUIImagePtr LLFolderBridge::getIcon() const +{ + LLAssetType::EType preferred_type = LLAssetType::AT_NONE; + LLViewerInventoryCategory* cat = getCategory(); + if(cat) + { + preferred_type = cat->getPreferredType(); + } + return getIcon(preferred_type); +} + +LLUIImagePtr LLFolderBridge::getIcon(LLAssetType::EType preferred_type) +{ + // we only have one folder image now + return LLUI::getUIImage("Inv_FolderClosed"); +} + +BOOL LLFolderBridge::renameItem(const std::string& new_name) +{ + if(!isItemRenameable()) + return FALSE; + LLInventoryModel* model = getInventoryModel(); + if(!model) + return FALSE; + LLViewerInventoryCategory* cat = getCategory(); + if(cat && (cat->getName() != new_name)) + { + LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat); + new_cat->rename(new_name); + new_cat->updateServer(FALSE); + model->updateCategory(new_cat); + + model->notifyObservers(); + } + // return FALSE because we either notified observers (& therefore + // rebuilt) or we didn't update. + return FALSE; +} + +BOOL LLFolderBridge::removeItem() +{ + if(!isItemRemovable()) + { + return FALSE; + } + // move it to the trash + LLPreview::hide(mUUID); + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + + LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + + // Look for any gestures and deactivate them + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE ); + + S32 i; + for (i = 0; i < descendent_items.count(); i++) + { + LLInventoryItem* item = descendent_items[i]; + if (item->getType() == LLAssetType::AT_GESTURE + && LLGestureManager::instance().isGestureActive(item->getUUID())) + { + LLGestureManager::instance().deactivateGesture(item->getUUID()); + } + } + + // go ahead and do the normal remove if no 'last calling + // cards' are being removed. + LLViewerInventoryCategory* cat = getCategory(); + if(cat) + { + LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE); + } + + return TRUE; +} + +void LLFolderBridge::pasteFromClipboard() +{ + LLInventoryModel* model = getInventoryModel(); + if(model && isClipboardPasteable()) + { + LLInventoryItem* item = NULL; + LLDynamicArray<LLUUID> objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + const LLUUID parent_id(mUUID); + for(S32 i = 0; i < count; i++) + { + item = model->getItem(objects.get(i)); + if (item) + { + if(LLInventoryClipboard::instance().isCutMode()) + { + // move_inventory_item() is not enough, + //we have to update inventory locally too + changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE); + } + else + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + parent_id, + std::string(), + LLPointer<LLInventoryCallback>(NULL)); + } + } + } + } +} + +void LLFolderBridge::pasteLinkFromClipboard() +{ + const LLInventoryModel* model = getInventoryModel(); + if(model) + { + LLDynamicArray<LLUUID> objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + LLUUID parent_id(mUUID); + for(S32 i = 0; i < count; i++) + { + const LLUUID &object_id = objects.get(i); +#if SUPPORT_ENSEMBLES + if (LLInventoryCategory *cat = model->getCategory(object_id)) + { + link_inventory_item( + gAgent.getID(), + cat->getUUID(), + parent_id, + cat->getName(), + LLAssetType::AT_LINK_FOLDER, + LLPointer<LLInventoryCallback>(NULL)); + } + else +#endif + if (LLInventoryItem *item = model->getItem(object_id)) + { + link_inventory_item( + gAgent.getID(), + item->getUUID(), + parent_id, + item->getName(), + LLAssetType::AT_LINK, + LLPointer<LLInventoryCallback>(NULL)); + } + } + } +} + +void LLFolderBridge::staticFolderOptionsMenu() +{ + if (!sSelf) return; + sSelf->folderOptionsMenu(); +} + +void LLFolderBridge::folderOptionsMenu() +{ + std::vector<std::string> disabled_items; + + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + + const LLInventoryCategory* category = model->getCategory(mUUID); + LLAssetType::EType type = category->getPreferredType(); + const bool is_default_folder = category && LLAssetType::lookupIsProtectedCategoryType(type); + // BAP change once we're no longer treating regular categories as ensembles. + const bool is_ensemble = category && (type == LLAssetType::AT_NONE || + LLAssetType::lookupIsEnsembleCategoryType(type)); + + // calling card related functionality for folders. + + // Only enable calling-card related options for non-default folders. + if (!is_default_folder) + { + LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); + if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) + { + mItems.push_back(std::string("Calling Card Separator")); + mItems.push_back(std::string("Conference Chat Folder")); + mItems.push_back(std::string("IM All Contacts In Folder")); + } + } + + // wearables related functionality for folders. + //is_wearable + LLFindWearables is_wearable; + LLIsType is_object( LLAssetType::AT_OBJECT ); + LLIsType is_gesture( LLAssetType::AT_GESTURE ); + + if (mWearables || + checkFolderForContentsOfType(model, is_wearable) || + checkFolderForContentsOfType(model, is_object) || + checkFolderForContentsOfType(model, is_gesture) ) + { + mItems.push_back(std::string("Folder Wearables Separator")); + + // Only enable add/replace outfit for non-default folders. + if (!is_default_folder) + { + mItems.push_back(std::string("Add To Outfit")); + mItems.push_back(std::string("Replace Outfit")); + } + if (is_ensemble) + { + mItems.push_back(std::string("Wear As Ensemble")); + } + mItems.push_back(std::string("Take Off Items")); + } + hide_context_entries(*mMenu, mItems, disabled_items); +} + +BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + model->collectDescendentsIf(mUUID, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_type); + return ((item_array.count() > 0) ? TRUE : FALSE ); +} + +// Flags unused +void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + mItems.clear(); + mDisabledItems.clear(); + + lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; +// std::vector<std::string> disabled_items; + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + + mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point) + mDisabledItems.clear(); //adding code to clear out disabled members from previous + if (lost_and_found_id == mUUID) + { + // This is the lost+found folder. + mItems.push_back(std::string("Empty Lost And Found")); + } + + if(trash_id == mUUID) + { + // This is the trash. + mItems.push_back(std::string("Empty Trash")); + } + else if(model->isObjectDescendentOf(mUUID, trash_id)) + { + // This is a folder in the trash. + mItems.clear(); // clear any items that used to exist + mItems.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + mDisabledItems.push_back(std::string("Purge Item")); + } + + mItems.push_back(std::string("Restore Item")); + } + else if(isAgentInventory()) // do not allow creating in library + { + LLViewerInventoryCategory *cat = getCategory(); + + // BAP removed protected check to re-enable standard ops in untyped folders. + // Not sure what the right thing is to do here. + if (!isCOFFolder() && cat /*&& + LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/) + { + // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. + if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) + mItems.push_back(std::string("New Folder")); + mItems.push_back(std::string("New Script")); + mItems.push_back(std::string("New Note")); + mItems.push_back(std::string("New Gesture")); + mItems.push_back(std::string("New Clothes")); + mItems.push_back(std::string("New Body Parts")); + mItems.push_back(std::string("Change Type")); + + LLViewerInventoryCategory *cat = getCategory(); + if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())) + { + mDisabledItems.push_back(std::string("Change Type")); + } + + getClipboardEntries(false, mItems, mDisabledItems, flags); + } + else + { + // Want some but not all of the items from getClipboardEntries for outfits. + if (cat && cat->getPreferredType()==LLAssetType::AT_OUTFIT) + { + mItems.push_back(std::string("Rename")); + mItems.push_back(std::string("Delete")); + } + } + + //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06 + mCallingCards = mWearables = FALSE; + + LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); + if (checkFolderForContentsOfType(model, is_callingcard)) + { + mCallingCards=TRUE; + } + + LLFindWearables is_wearable; + LLIsType is_object( LLAssetType::AT_OBJECT ); + LLIsType is_gesture( LLAssetType::AT_GESTURE ); + + if (checkFolderForContentsOfType(model, is_wearable) || + checkFolderForContentsOfType(model, is_object) || + checkFolderForContentsOfType(model, is_gesture) ) + { + mWearables=TRUE; + } + + mMenu = &menu; + sSelf = this; + LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE); + + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); + if (category) + { + folders.push_back(category->getUUID()); + } + fetch->fetchDescendents(folders); + inc_busy_count(); + if(fetch->isEverythingComplete()) + { + // everything is already here - call done. + fetch->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(fetch); + } + } + else + { + mItems.push_back(std::string("--no options--")); + mDisabledItems.push_back(std::string("--no options--")); + } + hide_context_entries(menu, mItems, mDisabledItems); +} + +BOOL LLFolderBridge::hasChildren() const +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + LLInventoryModel::EHasChildren has_children; + has_children = gInventory.categoryHasChildren(mUUID); + return has_children != LLInventoryModel::CHILDREN_NO; +} + +BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data) +{ + //llinfos << "LLFolderBridge::dragOrDrop()" << llendl; + BOOL accept = FALSE; + switch(cargo_type) + { + case DAD_TEXTURE: + case DAD_SOUND: + case DAD_CALLINGCARD: + case DAD_LANDMARK: + case DAD_SCRIPT: + case DAD_OBJECT: + case DAD_NOTECARD: + case DAD_CLOTHING: + case DAD_BODYPART: + case DAD_ANIMATION: + case DAD_GESTURE: + case DAD_LINK: + accept = dragItemIntoFolder((LLInventoryItem*)cargo_data, + drop); + break; + case DAD_CATEGORY: + if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID)) + { + accept = FALSE; + } + else + { + accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop); + } + break; + default: + break; + } + return accept; +} + +LLViewerInventoryCategory* LLFolderBridge::getCategory() const +{ + LLViewerInventoryCategory* cat = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + cat = (LLViewerInventoryCategory*)model->getCategory(mUUID); + } + return cat; +} + + +// static +void LLFolderBridge::pasteClipboard(void* user_data) +{ + LLFolderBridge* self = (LLFolderBridge*)user_data; + if(self) self->pasteFromClipboard(); +} + +void LLFolderBridge::createNewCategory(void* user_data) +{ + LLFolderBridge* bridge = (LLFolderBridge*)user_data; + if(!bridge) return; + LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get()); + if (!panel) return; + LLInventoryModel* model = panel->getModel(); + if(!model) return; + LLUUID id; + id = model->createNewCategory(bridge->getUUID(), + LLAssetType::AT_NONE, + LLStringUtil::null); + model->notifyObservers(); + + // At this point, the bridge has probably been deleted, but the + // view is still there. + panel->setSelection(id, TAKE_FOCUS_YES); +} + +void LLFolderBridge::createNewShirt(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHIRT); +} + +void LLFolderBridge::createNewPants(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PANTS); +} + +void LLFolderBridge::createNewShoes(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHOES); +} + +void LLFolderBridge::createNewSocks(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SOCKS); +} + +void LLFolderBridge::createNewJacket(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_JACKET); +} + +void LLFolderBridge::createNewSkirt(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIRT); +} + +void LLFolderBridge::createNewGloves(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_GLOVES); +} + +void LLFolderBridge::createNewUndershirt(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERSHIRT); +} + +void LLFolderBridge::createNewUnderpants(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS); +} + +void LLFolderBridge::createNewShape(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE); +} + +void LLFolderBridge::createNewSkin(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIN); +} + +void LLFolderBridge::createNewHair(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_HAIR); +} + +void LLFolderBridge::createNewEyes(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES); +} + +// static +void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type) +{ + if(!bridge) return; + LLUUID parent_id = bridge->getUUID(); + createWearable(parent_id, type); +} + +// Separate function so can be called by global menu as well as right-click +// menu. +// static +void LLFolderBridge::createWearable(LLUUID parent_id, EWearableType type) +{ + LLWearable* wearable = LLWearableList::instance().createNewWearable(type); + LLAssetType::EType asset_type = wearable->getAssetType(); + LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE; + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), + parent_id, wearable->getTransactionID(), wearable->getName(), + wearable->getDescription(), asset_type, inv_type, wearable->getType(), + wearable->getPermissions().getMaskNextOwner(), + LLPointer<LLInventoryCallback>(NULL)); +} + +void LLFolderBridge::modifyOutfit(BOOL append) +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLViewerInventoryCategory* cat = getCategory(); + if(!cat) return; + + // BAP - was: + // wear_inventory_category_on_avatar( cat, append ); + LLAppearanceManager::wearInventoryCategory( cat, FALSE, append ); +} + +// helper stuff +bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv) +{ + LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData; + LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID); + S32 option = LLNotification::getSelectedOption(notification, response); + + if(option == 0 && object) + { + if (cat_and_wear && cat_and_wear->mWear) + { + InventoryObjectList inventory_objects; + object->getInventoryContents(inventory_objects); + int contents_count = inventory_objects.size()-1; //subtract one for containing folder + + LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count); + gInventory.addObserver(inventoryObserver); + } + + two_uuids_list_t::iterator move_it; + for (move_it = move_inv->mMoveList.begin(); + move_it != move_inv->mMoveList.end(); + ++move_it) + { + object->moveInventory(move_it->first, move_it->second); + } + + // update the UI. + dialog_refresh_all(); + } + + if (move_inv->mCallback) + { + move_inv->mCallback(option, move_inv->mUserData); + } + + delete move_inv; + return false; +} + +/* +Next functions intended to reorder items in the inventory folder and save order on server +Is now used for Favorites folder. + +*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel +*/ +void saveItemsOrder(LLInventoryModel::item_array_t& items) +{ + int sortField = 0; + + // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field + for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) + { + LLViewerInventoryItem* item = *i; + + item->setSortField(++sortField); + item->setComplete(TRUE); + item->updateServer(FALSE); + + gInventory.updateItem(item); + } + + gInventory.notifyObservers(); +} + +LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id) +{ + LLInventoryModel::item_array_t::iterator result = items.end(); + + for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) + { + if ((*i)->getUUID() == id) + { + result = i; + break; + } + } + + return result; +} + +void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId) +{ + LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId); + LLViewerInventoryItem* destItem = gInventory.getItem(destItemId); + + items.erase(findItemByUUID(items, srcItem->getUUID())); + items.insert(findItemByUUID(items, destItem->getUUID()), srcItem); +} + +BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, + BOOL drop) +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + + // cannot drag into library + if(!isAgentInventory()) + { + return FALSE; + } + + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if(!avatar) return FALSE; + + LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); + BOOL accept = FALSE; + LLViewerObject* object = NULL; + if(LLToolDragAndDrop::SOURCE_AGENT == source) + { + + BOOL is_movable = TRUE; + switch( inv_item->getActualType() ) + { + case LLAssetType::AT_ROOT_CATEGORY: + is_movable = FALSE; + break; + + case LLAssetType::AT_CATEGORY: + is_movable = !LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)inv_item)->getPreferredType()); + break; + default: + break; + } + + LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); + LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); + BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT); + + if(is_movable && move_is_into_trash) + { + switch(inv_item->getType()) + { + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID()); + break; + + case LLAssetType::AT_OBJECT: + is_movable = !avatar->isWearingAttachment(inv_item->getUUID()); + break; + default: + break; + } + } + + if ( is_movable ) + { + // Don't allow creating duplicates in the Calling Card/Friends + // subfolders, see bug EXT-1599. Check is item direct descendent + // of target folder and forbid item's movement if it so. + // Note: isItemDirectDescendentOfCategory checks if + // passed category is in the Calling Card/Friends folder + is_movable = ! LLFriendCardsManager::instance() + .isObjDirectDescendentOfCategory (inv_item, getCategory()); + } + + LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + + // we can move item inside a folder only if this folder is Favorites. See EXT-719 + accept = is_movable && ((mUUID != inv_item->getParentUUID()) || (mUUID == favorites_id)); + if(accept && drop) + { + if (inv_item->getType() == LLAssetType::AT_GESTURE + && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) + { + LLGestureManager::instance().deactivateGesture(inv_item->getUUID()); + } + // If an item is being dragged between windows, unselect + // everything in the active window so that we don't follow + // the selection to its new location (which is very + // annoying). + if (LLFloaterInventory::getActiveInventory()) + { + LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); + LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + if (active_panel && (panel != active_panel)) + { + active_panel->unSelectAll(); + } + } + + // if dragging from/into favorites folder only reorder items + if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID)) + { + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLIsType is_type(LLAssetType::AT_LANDMARK); + model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + + LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; + if (itemp) + { + LLUUID srcItemId = inv_item->getUUID(); + LLUUID destItemId = itemp->getListener()->getUUID(); + + // update order + updateItemsOrder(items, srcItemId, destItemId); + + saveItemsOrder(items); + } + } + else if (favorites_id == mUUID) // if target is the favorites folder we use copy + { + copy_inventory_item( + gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + mUUID, + std::string(), + LLPointer<LLInventoryCallback>(NULL)); + } + else if (move_is_into_current_outfit || move_is_into_outfit) + { + // BAP - should skip if dup. + if (move_is_into_current_outfit) + { + LLAppearanceManager::wearItem(inv_item); + } + else + { + LLPointer<LLInventoryCallback> cb = NULL; + link_inventory_item( + gAgent.getID(), + inv_item->getUUID(), + mUUID, + std::string(), + LLAssetType::AT_LINK, + cb); + } + } + else + { + // restamp if the move is into the trash. + LLInvFVBridge::changeItemParent( + model, + (LLViewerInventoryItem*)inv_item, + mUUID, + move_is_into_trash); + } + } + } + else if(LLToolDragAndDrop::SOURCE_WORLD == source) + { + // Make sure the object exists. If we allowed dragging from + // anonymous objects, it would be possible to bypass + // permissions. + object = gObjectList.findObject(inv_item->getParentUUID()); + if(!object) + { + llinfos << "Object not found for drop." << llendl; + return FALSE; + } + + // coming from a task. Need to figure out if the person can + // move/copy this item. + LLPermissions perm(inv_item->getPermissions()); + BOOL is_move = FALSE; + if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) + && perm.allowTransferTo(gAgent.getID()))) +// || gAgent.isGodlike()) + + { + accept = TRUE; + } + else if(object->permYouOwner()) + { + // If the object cannot be copied, but the object the + // inventory is owned by the agent, then the item can be + // moved from the task to agent inventory. + is_move = TRUE; + accept = TRUE; + } + if(drop && accept) + { + LLMoveInv* move_inv = new LLMoveInv; + move_inv->mObjectID = inv_item->getParentUUID(); + two_uuids_t item_pair(mUUID, inv_item->getUUID()); + move_inv->mMoveList.push_back(item_pair); + move_inv->mCallback = NULL; + move_inv->mUserData = NULL; + if(is_move) + { + warn_move_inventory(object, move_inv); + } + else + { + LLNotification::Params params("MoveInventoryFromObject"); + params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); + LLNotifications::instance().forceResponse(params, 0); + } + } + + } + else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) + { + accept = TRUE; + if(drop) + { + copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(), + LLToolDragAndDrop::getInstance()->getSourceID(), inv_item); + } + } + else if(LLToolDragAndDrop::SOURCE_LIBRARY == source) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item; + if(item && item->isComplete()) + { + accept = TRUE; + if(drop) + { + copy_inventory_item( + gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + mUUID, + std::string(), + LLPointer<LLInventoryCallback>(NULL)); + } + } + } + else + { + llwarns << "unhandled drag source" << llendl; + } + return accept; +} + +// +=================================================+ +// | LLScriptBridge (DEPRECTED) | +// +=================================================+ + +LLUIImagePtr LLScriptBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE); +} + +// +=================================================+ +// | LLTextureBridge | +// +=================================================+ + +LLUIImagePtr LLTextureBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE); +} + +void LLTextureBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +} + +// +=================================================+ +// | LLSoundBridge | +// +=================================================+ + +LLUIImagePtr LLSoundBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE); +} + +void LLSoundBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* +// Changed this back to the way it USED to work: +// only open the preview dialog through the contextual right-click menu +// double-click just plays the sound + + LLViewerInventoryItem* item = getItem(); + if(item) + { + openSoundPreview((void*)this); + //send_uuid_sound_trigger(item->getAssetUUID(), 1.0); + } +*/ +} + +void LLSoundBridge::previewItem() +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + send_sound_trigger(item->getAssetUUID(), 1.0); + } +} + +void LLSoundBridge::openSoundPreview(void* which) +{ + LLSoundBridge *me = (LLSoundBridge *)which; + LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES); +} + +void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLTextureBridge::buildContextMenu()" << llendl; + std::vector<std::string> items; + std::vector<std::string> disabled_items; + + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Sound Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + } + + items.push_back(std::string("Sound Separator")); + items.push_back(std::string("Sound Play")); + + hide_context_entries(menu, items, disabled_items); +} + +// +=================================================+ +// | LLLandmarkBridge | +// +=================================================+ + +LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) : +LLItemBridge(inventory, uuid) +{ + mVisited = FALSE; + if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED) + { + mVisited = TRUE; + } +} + +LLUIImagePtr LLLandmarkBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE); +} + +void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + std::vector<std::string> items; + std::vector<std::string> disabled_items; + + lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl; + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Landmark Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + } + + items.push_back(std::string("Landmark Separator")); + items.push_back(std::string("About Landmark")); + + // Disable "About Landmark" menu item for + // multiple landmarks selected. Only one landmark + // info panel can be shown at a time. + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("About Landmark")); + } + + hide_context_entries(menu, items, disabled_items); +} + +// Convenience function for the two functions below. +void teleport_via_landmark(const LLUUID& asset_id) +{ + gAgent.teleportViaLandmark( asset_id ); + + // we now automatically track the landmark you're teleporting to + // because you'll probably arrive at a telehub instead + LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); + if( floater_world_map ) + { + floater_world_map->trackLandmark( asset_id ); + } +} + +// virtual +void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("teleport" == action) + { + LLViewerInventoryItem* item = getItem(); + if(item) + { + teleport_via_landmark(item->getAssetUUID()); + } + } + else if ("about" == action) + { + LLViewerInventoryItem* item = getItem(); + if(item) + { + LLSD key; + key["type"] = "landmark"; + key["id"] = item->getUUID(); + + LLSideTray::getInstance()->showPanel("panel_places", key); + } + } + else + { + LLItemBridge::performAction(folder, model, action); + } +} + +static bool open_landmark_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + + LLUUID asset_id = notification["payload"]["asset_id"].asUUID(); + if (option == 0) + { + teleport_via_landmark(asset_id); + } + + return false; +} +static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback); + + +void LLLandmarkBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* + LLViewerInventoryItem* item = getItem(); + if( item ) + { + // Opening (double-clicking) a landmark immediately teleports, + // but warns you the first time. + // open_landmark(item); + LLSD payload; + payload["asset_id"] = item->getAssetUUID(); + LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); + } +*/ +} + + +// +=================================================+ +// | LLCallingCardObserver | +// +=================================================+ +void LLCallingCardObserver::changed(U32 mask) +{ + mBridgep->refreshFolderViewItem(); +} + +// +=================================================+ +// | LLCallingCardBridge | +// +=================================================+ + +LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) : + LLItemBridge(inventory, uuid) +{ + mObserver = new LLCallingCardObserver(this); + LLAvatarTracker::instance().addObserver(mObserver); +} + +LLCallingCardBridge::~LLCallingCardBridge() +{ + LLAvatarTracker::instance().removeObserver(mObserver); + delete mObserver; +} + +void LLCallingCardBridge::refreshFolderViewItem() +{ + LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; + if (itemp) + { + itemp->refresh(); + } +} + +// virtual +void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("begin_im" == action) + { + LLViewerInventoryItem *item = getItem(); + if (item && (item->getCreatorUUID() != gAgent.getID()) && + (!item->getCreatorUUID().isNull())) + { + std::string callingcard_name; + gCacheName->getFullName(item->getCreatorUUID(), callingcard_name); + gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); + } + } + else if ("lure" == action) + { + LLViewerInventoryItem *item = getItem(); + if (item && (item->getCreatorUUID() != gAgent.getID()) && + (!item->getCreatorUUID().isNull())) + { + LLAvatarActions::offerTeleport(item->getCreatorUUID()); + } + } + else LLItemBridge::performAction(folder, model, action); +} + +LLUIImagePtr LLCallingCardBridge::getIcon() const +{ + BOOL online = FALSE; + LLViewerInventoryItem* item = getItem(); + if(item) + { + online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()); + } + return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE); +} + +std::string LLCallingCardBridge::getLabelSuffix() const +{ + LLViewerInventoryItem* item = getItem(); + if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) ) + { + return LLItemBridge::getLabelSuffix() + " (online)"; + } + else + { + return LLItemBridge::getLabelSuffix(); + } +} + +void LLCallingCardBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* + LLViewerInventoryItem* item = getItem(); + if(item && !item->getCreatorUUID().isNull()) + { + LLAvatarActions::showProfile(item->getCreatorUUID()); + } +*/ +} + +void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl; + std::vector<std::string> items; + std::vector<std::string> disabled_items; + + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + LLInventoryItem* item = getItem(); + BOOL good_card = (item + && (LLUUID::null != item->getCreatorUUID()) + && (item->getCreatorUUID() != gAgent.getID())); + BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID())); + items.push_back(std::string("Send Instant Message Separator")); + items.push_back(std::string("Send Instant Message")); + items.push_back(std::string("Offer Teleport...")); + items.push_back(std::string("Conference Chat")); + + if (!good_card) + { + disabled_items.push_back(std::string("Send Instant Message")); + } + if (!good_card || !user_online) + { + disabled_items.push_back(std::string("Offer Teleport...")); + disabled_items.push_back(std::string("Conference Chat")); + } + } + hide_context_entries(menu, items, disabled_items); +} + +BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data) +{ + LLViewerInventoryItem* item = getItem(); + BOOL rv = FALSE; + if(item) + { + // check the type + switch(cargo_type) + { + case DAD_TEXTURE: + case DAD_SOUND: + case DAD_LANDMARK: + case DAD_SCRIPT: + case DAD_CLOTHING: + case DAD_OBJECT: + case DAD_NOTECARD: + case DAD_BODYPART: + case DAD_ANIMATION: + case DAD_GESTURE: + { + LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; + const LLPermissions& perm = inv_item->getPermissions(); + if(gInventory.getItem(inv_item->getUUID()) + && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID())) + { + rv = TRUE; + if(drop) + { + LLToolDragAndDrop::giveInventory(item->getCreatorUUID(), + (LLInventoryItem*)cargo_data); + } + } + else + { + // It's not in the user's inventory (it's probably in + // an object's contents), so disallow dragging it here. + // You can't give something you don't yet have. + rv = FALSE; + } + break; + } + case DAD_CATEGORY: + { + LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data; + if( gInventory.getCategory( inv_cat->getUUID() ) ) + { + rv = TRUE; + if(drop) + { + LLToolDragAndDrop::giveInventoryCategory( + item->getCreatorUUID(), + inv_cat); + } + } + else + { + // It's not in the user's inventory (it's probably in + // an object's contents), so disallow dragging it here. + // You can't give something you don't yet have. + rv = FALSE; + } + break; + } + default: + break; + } + } + return rv; +} + +BOOL LLCallingCardBridge::removeItem() +{ + if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem())) + { + LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID()); + return FALSE; + } + else + { + return LLItemBridge::removeItem(); + } +} +// +=================================================+ +// | LLNotecardBridge | +// +=================================================+ + +LLUIImagePtr LLNotecardBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE); +} + +void LLNotecardBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } + +/* + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES); + } +*/ +} + + +// +=================================================+ +// | LLGestureBridge | +// +=================================================+ + +LLUIImagePtr LLGestureBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE); +} + +LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const +{ + if( LLGestureManager::instance().isGestureActive(mUUID) ) + { + return LLFontGL::BOLD; + } + else + { + return LLFontGL::NORMAL; + } +} + +std::string LLGestureBridge::getLabelSuffix() const +{ + if( LLGestureManager::instance().isGestureActive(mUUID) ) + { + return LLItemBridge::getLabelSuffix() + " (active)"; + } + else + { + return LLItemBridge::getLabelSuffix(); + } +} + +// virtual +void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("activate" == action) + { + LLGestureManager::instance().activateGesture(mUUID); + + LLViewerInventoryItem* item = gInventory.getItem(mUUID); + if (!item) return; + + // Since we just changed the suffix to indicate (active) + // the server doesn't need to know, just the viewer. + gInventory.updateItem(item); + gInventory.notifyObservers(); + } + else if ("deactivate" == action) + { + LLGestureManager::instance().deactivateGesture(mUUID); + + LLViewerInventoryItem* item = gInventory.getItem(mUUID); + if (!item) return; + + // Since we just changed the suffix to indicate (active) + // the server doesn't need to know, just the viewer. + gInventory.updateItem(item); + gInventory.notifyObservers(); + } + else LLItemBridge::performAction(folder, model, action); +} + +void LLGestureBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); + preview->setFocus(TRUE); + } +*/ +} + +BOOL LLGestureBridge::removeItem() +{ + // Force close the preview window, if it exists + LLGestureManager::instance().deactivateGesture(mUUID); + return LLItemBridge::removeItem(); +} + +void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLGestureBridge::buildContextMenu()" << llendl; + std::vector<std::string> items; + std::vector<std::string> disabled_items; + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + items.push_back(std::string("Gesture Separator")); + items.push_back(std::string("Activate")); + items.push_back(std::string("Deactivate")); + } + hide_context_entries(menu, items, disabled_items); +} + +// +=================================================+ +// | LLAnimationBridge | +// +=================================================+ + +LLUIImagePtr LLAnimationBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE); +} + +void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + std::vector<std::string> items; + std::vector<std::string> disabled_items; + + lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl; + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Animation Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + } + + items.push_back(std::string("Animation Separator")); + items.push_back(std::string("Animation Play")); + items.push_back(std::string("Animation Audition")); + + hide_context_entries(menu, items, disabled_items); + +} + +// virtual +void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ((action == "playworld") || (action == "playlocal")) + { + if (getItem()) + { + LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE; + if ("playworld" == action) activate = LLPreviewAnim::PLAY; + if ("playlocal" == action) activate = LLPreviewAnim::AUDITION; + + LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID)); + if (preview) + { + preview->activate(activate); + } + } + } + else + { + LLItemBridge::performAction(folder, model, action); + } +} + +void LLAnimationBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); + } +*/ +} + +// +=================================================+ +// | LLObjectBridge | +// +=================================================+ + +// static +LLUUID LLObjectBridge::sContextMenuItemID; + +LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) : +LLItemBridge(inventory, uuid), mInvType(type) +{ + mAttachPt = (flags & 0xff); // low bye of inventory flags + + mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE; +} + +BOOL LLObjectBridge::isItemRemovable() +{ + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if(!avatar) return FALSE; + if(avatar->isWearingAttachment(mUUID)) return FALSE; + return LLInvFVBridge::isItemRemovable(); +} + +LLUIImagePtr LLObjectBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject ); +} + +LLInventoryObject* LLObjectBridge::getObject() const +{ + LLInventoryObject* object = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + object = (LLInventoryObject*)model->getObject(mUUID); + } + return object; +} + +// virtual +void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("attach" == action) + { + LLUUID object_id = mUUID; + LLViewerInventoryItem* item; + item = (LLViewerInventoryItem*)gInventory.getItem(object_id); + if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID())) + { + rez_attachment(item, NULL); + } + else if(item && item->isComplete()) + { + // must be in library. copy it to our inventory and put it on. + LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + gFocusMgr.setKeyboardFocus(NULL); + } + else if ("detach" == action) + { + LLInventoryItem* item = gInventory.getItem(mUUID); + if(item) + { + gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); + gMessageSystem->sendReliable( gAgent.getRegion()->getHost()); + } + // this object might have been selected, so let the selection manager know it's gone now + LLViewerObject *found_obj = + gObjectList.findObject(item->getUUID()); + if (found_obj) + { + LLSelectMgr::getInstance()->remove(found_obj); + } + else + { + llwarns << "object not found - ignoring" << llendl; + } + } + else LLItemBridge::performAction(folder, model, action); +} + +void LLObjectBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } + + LLSD key; + key["id"] = mUUID; + LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); + + /* + LLFloaterReg::showInstance("properties", mUUID); + */ +} + +LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const +{ + U8 font = LLFontGL::NORMAL; + + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if( avatar && avatar->isWearingAttachment( mUUID ) ) + { + font |= LLFontGL::BOLD; + } + + LLInventoryItem* item = getItem(); + if (item && item->getIsLinkType()) + { + font |= LLFontGL::ITALIC; + } + + return (LLFontGL::StyleFlags)font; +} + +std::string LLObjectBridge::getLabelSuffix() const +{ + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if( avatar && avatar->isWearingAttachment( mUUID ) ) + { + std::string attachment_point_name = avatar->getAttachedPointName(mUUID); + LLStringUtil::toLower(attachment_point_name); + + LLStringUtil::format_map_t args; + args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str(); + return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); + } + else + { + return LLItemBridge::getLabelSuffix(); + } +} + +void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment) +{ + LLSD payload; + payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link. + + S32 attach_pt = 0; + if (gAgent.getAvatarObject() && attachment) + { + for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin(); + iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter) + { + if (iter->second == attachment) + { + attach_pt = iter->first; + break; + } + } + } + + payload["attachment_point"] = attach_pt; + +#if !ENABLE_MULTIATTACHMENTS + if (attachment && attachment->getNumObjects() > 0) + { + LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); + } + else +#endif + { + LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/); + } +} + +bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response) +{ + LLVOAvatar *avatarp = gAgent.getAvatarObject(); + + if (!avatarp->canAttachMoreObjects()) + { + LLSD args; + args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS); + LLNotifications::instance().add("MaxAttachmentsOnOutfit", args); + return false; + } + + S32 option = LLNotification::getSelectedOption(notification, response); + if (option == 0/*YES*/) + { + LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID()); + + if (itemp) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID()); + msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner()); + U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); +#if ENABLE_MULTIATTACHMENTS + attachment_pt |= ATTACHMENT_ADD; +#endif + msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); + pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions()); + msg->addStringFast(_PREHASH_Name, itemp->getName()); + msg->addStringFast(_PREHASH_Description, itemp->getDescription()); + msg->sendReliable(gAgent.getRegion()->getHost()); + } + } + return false; +} +static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_replace_attachment_rez); + +void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + std::vector<std::string> items; + std::vector<std::string> disabled_items; + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + LLInventoryItem* item = getItem(); + if (item && item->getIsLinkType()) + { + items.push_back(std::string("Goto Link")); + } + + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + LLObjectBridge::sContextMenuItemID = mUUID; + + if(item) + { + LLVOAvatarSelf* avatarp = gAgent.getAvatarObject(); + if( !avatarp ) + { + return; + } + + if( avatarp->isWearingAttachment( mUUID ) ) + { + items.push_back(std::string("Detach From Yourself")); + } + else + if( !isInTrash() && !isLinkedObjectInTrash() ) + { + items.push_back(std::string("Attach Separator")); + items.push_back(std::string("Object Wear")); + items.push_back(std::string("Attach To")); + items.push_back(std::string("Attach To HUD")); + // commented out for DEV-32347 + //items.push_back(std::string("Restore to Last Position")); + + if (!avatarp->canAttachMoreObjects()) + { + disabled_items.push_back(std::string("Object Wear")); + disabled_items.push_back(std::string("Attach To")); + disabled_items.push_back(std::string("Attach To HUD")); + } + LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE); + LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE); + LLVOAvatar *avatarp = gAgent.getAvatarObject(); + if (attach_menu + && (attach_menu->getChildCount() == 0) + && attach_hud_menu + && (attach_hud_menu->getChildCount() == 0) + && avatarp) + { + for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); + iter != avatarp->mAttachmentPoints.end(); ) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + LLMenuItemCallGL::Params p; + std::string submenu_name = attachment->getName(); + if (LLTrans::getString(submenu_name) != "") + { + p.name = (" ")+LLTrans::getString(submenu_name)+" "; + } + else + { + p.name = submenu_name; + } + LLSD cbparams; + cbparams["index"] = curiter->first; + cbparams["label"] = attachment->getName(); + p.on_click.function_name = "Inventory.AttachObject"; + p.on_click.parameter = LLSD(attachment->getName()); + p.on_enable.function_name = "Attachment.Label"; + p.on_enable.parameter = cbparams; + LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu; + LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent); + } + } + } + } + } + hide_context_entries(menu, items, disabled_items); +} + +BOOL LLObjectBridge::renameItem(const std::string& new_name) +{ + if(!isItemRenameable()) + return FALSE; + LLPreview::dirty(mUUID); + LLInventoryModel* model = getInventoryModel(); + if(!model) + return FALSE; + LLViewerInventoryItem* item = getItem(); + if(item && (item->getName() != new_name)) + { + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); + new_item->rename(new_name); + buildDisplayName(new_item, mDisplayName); + new_item->updateServer(FALSE); + model->updateItem(new_item); + + model->notifyObservers(); + + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if( avatar ) + { + LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() ); + if( obj ) + { + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); + LLSelectMgr::getInstance()->selectionSetObjectName( new_name ); + LLSelectMgr::getInstance()->deselectAll(); + } + } + } + // return FALSE because we either notified observers (& therefore + // rebuilt) or we didn't update. + return FALSE; +} + +// +=================================================+ +// | LLLSLTextBridge | +// +=================================================+ + +LLUIImagePtr LLLSLTextBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE); +} + +void LLLSLTextBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } + /* + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES); + } + */ +} + +// +=================================================+ +// | LLWearableBridge | +// +=================================================+ + +// *NOTE: hack to get from avatar inventory to avatar +void wear_inventory_item_on_avatar( LLInventoryItem* item ) +{ + if(item) + { + lldebugs << "wear_inventory_item_on_avatar( " << item->getName() + << " )" << llendl; + + LLAppearanceManager::wearItem(item); + } +} + +void wear_add_inventory_item_on_avatar( LLInventoryItem* item ) +{ + if(item) + { + lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName() + << " )" << llendl; + + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + LLWearableBridge::onWearAddOnAvatarArrived, + new LLUUID(item->getUUID())); + } +} + +void remove_inventory_category_from_avatar( LLInventoryCategory* category ) +{ + if(!category) return; + lldebugs << "remove_inventory_category_from_avatar( " << category->getName() + << " )" << llendl; + + + if( gFloaterCustomize ) + { + gFloaterCustomize->askToSaveIfDirty( + boost::bind(remove_inventory_category_from_avatar_step2, _1, category->getUUID())); + } + else + { + remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() ); + } +} + +struct OnRemoveStruct +{ + LLUUID mUUID; + OnRemoveStruct(const LLUUID& uuid): + mUUID(uuid) + { + } +}; + +void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id) +{ + + // Find all the wearables that are in the category's subtree. + lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl; + if(proceed) + { + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + LLFindWearables is_wearable; + gInventory.collectDescendentsIf(category_id, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_wearable); + S32 i; + S32 wearable_count = item_array.count(); + + LLInventoryModel::cat_array_t obj_cat_array; + LLInventoryModel::item_array_t obj_item_array; + LLIsType is_object( LLAssetType::AT_OBJECT ); + gInventory.collectDescendentsIf(category_id, + obj_cat_array, + obj_item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_object); + S32 obj_count = obj_item_array.count(); + + // Find all gestures in this folder + LLInventoryModel::cat_array_t gest_cat_array; + LLInventoryModel::item_array_t gest_item_array; + LLIsType is_gesture( LLAssetType::AT_GESTURE ); + gInventory.collectDescendentsIf(category_id, + gest_cat_array, + gest_item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_gesture); + S32 gest_count = gest_item_array.count(); + + if (wearable_count > 0) //Loop through wearables. If worn, remove. + { + for(i = 0; i < wearable_count; ++i) + { + if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) ) + { + LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(), + item_array.get(i)->getName(), + item_array.get(i)->getType(), + LLWearableBridge::onRemoveFromAvatarArrived, + new OnRemoveStruct(item_array.get(i)->getUUID())); + + } + } + } + + + if (obj_count > 0) + { + for(i = 0; i < obj_count; ++i) + { + gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() ); + + gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); + + // this object might have been selected, so let the selection manager know it's gone now + LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID()); + if (found_obj) + { + LLSelectMgr::getInstance()->remove(found_obj); + } + else + { + llwarns << "object not found, ignoring" << llendl; + } + } + } + + if (gest_count > 0) + { + for(i = 0; i < gest_count; ++i) + { + if ( LLGestureManager::instance().isGestureActive( gest_item_array.get(i)->getUUID()) ) + { + LLGestureManager::instance().deactivateGesture( gest_item_array.get(i)->getUUID() ); + gInventory.updateItem( gest_item_array.get(i) ); + gInventory.notifyObservers(); + } + + } + } + } +} + +BOOL LLWearableBridge::renameItem(const std::string& new_name) +{ + if( gAgentWearables.isWearingItem( mUUID ) ) + { + gAgentWearables.setWearableName( mUUID, new_name ); + } + return LLItemBridge::renameItem(new_name); +} + +BOOL LLWearableBridge::isItemRemovable() +{ + if (gAgentWearables.isWearingItem(mUUID)) return FALSE; + return LLInvFVBridge::isItemRemovable(); +} + +std::string LLWearableBridge::getLabelSuffix() const +{ + if( gAgentWearables.isWearingItem( mUUID ) ) + { + return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); + } + else + { + return LLItemBridge::getLabelSuffix(); + } +} + +LLUIImagePtr LLWearableBridge::getIcon() const +{ + return get_item_icon(mAssetType, mInvType, mWearableType, FALSE); +} + +// virtual +void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("wear" == action) + { + wearOnAvatar(); + } + else if ("wear_add" == action) + { + wearAddOnAvatar(); + } + else if ("edit" == action) + { + editOnAvatar(); + return; + } + else if ("take_off" == action) + { + if(gAgentWearables.isWearingItem(mUUID)) + { + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + LLWearableBridge::onRemoveFromAvatarArrived, + new OnRemoveStruct(mUUID)); + } + } + } + else LLItemBridge::performAction(folder, model, action); +} + +void LLWearableBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } + /* + if( isInTrash() ) + { + LLNotifications::instance().add("CannotWearTrash"); + } + else if(isAgentInventory()) + { + if( !gAgentWearables.isWearingItem( mUUID ) ) + { + wearOnAvatar(); + } + } + else + { + // must be in the inventory library. copy it to our inventory + // and put it on right away. + LLViewerInventoryItem* item = getItem(); + if(item && item->isComplete()) + { + LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else if(item) + { + // *TODO: We should fetch the item details, and then do + // the operation above. + LLNotifications::instance().add("CannotWearInfoNotComplete"); + } + } + */ +} + +void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLWearableBridge::buildContextMenu()" << llendl; + std::vector<std::string> items; + std::vector<std::string> disabled_items; + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere + BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM); + + // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976 + LLViewerInventoryItem* item = getItem(); + if( !no_open && item ) + { + no_open = (item->getType() == LLAssetType::AT_CLOTHING) || + (item->getType() == LLAssetType::AT_BODYPART); + } + if (!no_open) + { + items.push_back(std::string("Open")); + } + + if (item && item->getIsLinkType()) + { + items.push_back(std::string("Goto Link")); + } + + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + items.push_back(std::string("Wearable Separator")); + + items.push_back(std::string("Wearable Wear")); + items.push_back(std::string("Wearable Add")); + items.push_back(std::string("Wearable Edit")); + + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Wearable Edit")); + } + // Don't allow items to be worn if their baseobj is in the trash. + if (isLinkedObjectInTrash()) + { + disabled_items.push_back(std::string("Wearable Wear")); + disabled_items.push_back(std::string("Wearable Add")); + disabled_items.push_back(std::string("Wearable Edit")); + } + + // Disable wear and take off based on whether the item is worn. + if(item) + { + switch (item->getType()) + { + case LLAssetType::AT_CLOTHING: + items.push_back(std::string("Take Off")); + case LLAssetType::AT_BODYPART: + if (gAgentWearables.isWearingItem(item->getUUID())) + { + disabled_items.push_back(std::string("Wearable Wear")); + disabled_items.push_back(std::string("Wearable Add")); + } + else + { + disabled_items.push_back(std::string("Take Off")); + } + break; + default: + break; + } + } + } + hide_context_entries(menu, items, disabled_items); +} + +// Called from menus +// static +BOOL LLWearableBridge::canWearOnAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(!self) return FALSE; + if(!self->isAgentInventory()) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem(); + if(!item || !item->isComplete()) return FALSE; + } + return (!gAgentWearables.isWearingItem(self->mUUID)); +} + +// Called from menus +// static +void LLWearableBridge::onWearOnAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(!self) return; + self->wearOnAvatar(); +} + +void LLWearableBridge::wearOnAvatar() +{ + // Don't wear anything until initial wearables are loaded, can + // destroy clothing items. + if (!gAgentWearables.areWearablesLoaded()) + { + LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + return; + } + + LLViewerInventoryItem* item = getItem(); + if(item) + { + if(!isAgentInventory()) + { + LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else + { + wear_inventory_item_on_avatar(item); + } + } +} + +void LLWearableBridge::wearAddOnAvatar() +{ + // Don't wear anything until initial wearables are loaded, can + // destroy clothing items. + if (!gAgentWearables.areWearablesLoaded()) + { + LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + return; + } + + LLViewerInventoryItem* item = getItem(); + if(item) + { + if(!isAgentInventory()) + { + LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else + { + wear_add_inventory_item_on_avatar(item); + } + } +} + +// static +void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata ) +{ + LLUUID* item_id = (LLUUID*) userdata; + if(wearable) + { + LLViewerInventoryItem* item = NULL; + item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); + if(item) + { + if(item->getAssetUUID() == wearable->getAssetID()) + { + gAgentWearables.setWearableItem(item, wearable); + gInventory.notifyObservers(); + //self->getFolderItem()->refreshFromRoot(); + } + else + { + llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; + } + } + } + delete item_id; +} + +// static +// BAP remove the "add" code path once everything is fully COF-ified. +void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata ) +{ + LLUUID* item_id = (LLUUID*) userdata; + if(wearable) + { + LLViewerInventoryItem* item = NULL; + item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); + if(item) + { + if(item->getAssetUUID() == wearable->getAssetID()) + { + bool do_append = true; + gAgentWearables.setWearableItem(item, wearable, do_append); + gInventory.notifyObservers(); + //self->getFolderItem()->refreshFromRoot(); + } + else + { + llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; + } + } + } + delete item_id; +} + +// static +BOOL LLWearableBridge::canEditOnAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(!self) return FALSE; + + return (gAgentWearables.isWearingItem(self->mUUID)); +} + +// static +void LLWearableBridge::onEditOnAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(self) + { + self->editOnAvatar(); + } +} + +void LLWearableBridge::editOnAvatar() +{ + const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID); + if( wearable ) + { + // Set the tab to the right wearable. + if (gFloaterCustomize) + gFloaterCustomize->setCurrentWearableType( wearable->getType() ); + + if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() ) + { + // Start Avatar Customization + gAgent.changeCameraToCustomizeAvatar(); + } + } +} + +// static +BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if( self && (LLAssetType::AT_BODYPART != self->mAssetType) ) + { + return gAgentWearables.isWearingItem( self->mUUID ); + } + return FALSE; +} + +// static +void LLWearableBridge::onRemoveFromAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(!self) return; + if(gAgentWearables.isWearingItem(self->mUUID)) + { + LLViewerInventoryItem* item = self->getItem(); + if (item) + { + LLUUID parent_id = item->getParentUUID(); + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + onRemoveFromAvatarArrived, + new OnRemoveStruct(LLUUID(self->mUUID))); + } + } +} + +// static +void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, + void* userdata) +{ + OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata; + const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID); + if(wearable) + { + if( gAgentWearables.isWearingItem( item_id ) ) + { + EWearableType type = wearable->getType(); + + if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&& + //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) ) + { + // MULTI_WEARABLE: FIXME HACK - always remove all + bool do_remove_all = false; + gAgentWearables.removeWearable( type, do_remove_all, 0 ); + } + } + } + + // Find and remove this item from the COF. + LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::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(); + + delete on_remove_struct; +} + +LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type, + const LLUUID& uuid,LLInventoryModel* model) +{ + LLInvFVBridgeAction* action = NULL; + switch(asset_type) + { + case LLAssetType::AT_TEXTURE: + action = new LLTextureBridgeAction(uuid,model); + break; + + case LLAssetType::AT_SOUND: + action = new LLSoundBridgeAction(uuid,model); + break; + + case LLAssetType::AT_LANDMARK: + action = new LLLandmarkBridgeAction(uuid,model); + break; + + case LLAssetType::AT_CALLINGCARD: + action = new LLCallingCardBridgeAction(uuid,model); + break; + + case LLAssetType::AT_OBJECT: + action = new LLObjectBridgeAction(uuid,model); + break; + + case LLAssetType::AT_NOTECARD: + action = new LLNotecardBridgeAction(uuid,model); + break; + + case LLAssetType::AT_ANIMATION: + action = new LLAnimationBridgeAction(uuid,model); + break; + + case LLAssetType::AT_GESTURE: + action = new LLGestureBridgeAction(uuid,model); + break; + + case LLAssetType::AT_LSL_TEXT: + action = new LLLSLTextBridgeAction(uuid,model); + break; + + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + action = new LLWearableBridgeAction(uuid,model); + + break; + + default: + break; + } + return action; +} + +//static +void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type, + const LLUUID& uuid,LLInventoryModel* model) +{ + LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); + if(action) + { + action->doIt(); + delete action; + } +} + +//static +void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model) +{ + LLAssetType::EType asset_type = model->getItem(uuid)->getType(); + LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); + if(action) + { + action->doIt(); + delete action; + } +} + +LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const +{ + if(mModel) + return (LLViewerInventoryItem*)mModel->getItem(mUUID); + return NULL; +} + +//virtual +void LLTextureBridgeAction::doIt() +{ + if (getItem()) + { + LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); + } + + LLInvFVBridgeAction::doIt(); +} + +//virtual +void LLSoundBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES); + } + + LLInvFVBridgeAction::doIt(); +} + + +//virtual +void LLLandmarkBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if( item ) + { + // Opening (double-clicking) a landmark immediately teleports, + // but warns you the first time. + LLSD payload; + payload["asset_id"] = item->getAssetUUID(); + LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); + } + + LLInvFVBridgeAction::doIt(); +} + + +//virtual +void LLCallingCardBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if(item && item->getCreatorUUID().notNull()) + { + LLAvatarActions::showProfile(item->getCreatorUUID()); + } + + LLInvFVBridgeAction::doIt(); +} + +//virtual +void +LLNotecardBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES); + } + + LLInvFVBridgeAction::doIt(); +} + +//virtual +void LLGestureBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); + preview->setFocus(TRUE); + } + + LLInvFVBridgeAction::doIt(); +} + +//virtual +void LLAnimationBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); + } + + LLInvFVBridgeAction::doIt(); +} + + +//virtual +void LLObjectBridgeAction::doIt() +{ + LLFloaterReg::showInstance("properties", mUUID); + + LLInvFVBridgeAction::doIt(); +} + + +//virtual +void LLLSLTextBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES); + } + + LLInvFVBridgeAction::doIt(); +} + + +BOOL LLWearableBridgeAction::isInTrash() const +{ + if(!mModel) return FALSE; + LLUUID trash_id = mModel->findCategoryUUIDForType(LLAssetType::AT_TRASH); + return mModel->isObjectDescendentOf(mUUID, trash_id); +} + +BOOL LLWearableBridgeAction::isAgentInventory() const +{ + if(!mModel) return FALSE; + if(gInventory.getRootFolderID() == mUUID) return TRUE; + return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); +} + +void LLWearableBridgeAction::wearOnAvatar() +{ + // Don't wear anything until initial wearables are loaded, can + // destroy clothing items. + if (!gAgentWearables.areWearablesLoaded()) + { + LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + return; + } + + LLViewerInventoryItem* item = getItem(); + if(item) + { + if(!isAgentInventory()) + { + LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else + { + wear_inventory_item_on_avatar(item); + } + } +} + +//virtual +void LLWearableBridgeAction::doIt() +{ + if(isInTrash()) + { + LLNotifications::instance().add("CannotWearTrash"); + } + else if(isAgentInventory()) + { + if(!gAgentWearables.isWearingItem(mUUID)) + { + wearOnAvatar(); + } + } + else + { + // must be in the inventory library. copy it to our inventory + // and put it on right away. + LLViewerInventoryItem* item = getItem(); + if(item && item->isComplete()) + { + LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else if(item) + { + // *TODO: We should fetch the item details, and then do + // the operation above. + LLNotifications::instance().add("CannotWearInfoNotComplete"); + } + } + + LLInvFVBridgeAction::doIt(); +} + +// +=================================================+ +// | LLLinkItemBridge | +// +=================================================+ +// For broken links + +std::string LLLinkItemBridge::sPrefix("Link: "); + + +LLUIImagePtr LLLinkItemBridge::getIcon() const +{ + if (LLViewerInventoryItem *item = getItem()) + { + return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE); + } + return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE); +} + +void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + // *TODO: Translate + lldebugs << "LLLink::buildContextMenu()" << llendl; + std::vector<std::string> items; + std::vector<std::string> disabled_items; + + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Delete")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Delete")); + } + } + hide_context_entries(menu, items, disabled_items); +} + + +// +=================================================+ +// | LLLinkBridge | +// +=================================================+ +// For broken links. + +std::string LLLinkFolderBridge::sPrefix("Link: "); + + +LLUIImagePtr LLLinkFolderBridge::getIcon() const +{ + LLAssetType::EType preferred_type = LLAssetType::AT_NONE; + if (LLViewerInventoryItem *item = getItem()) + { + if (const LLViewerInventoryCategory* cat = item->getLinkedCategory()) + { + preferred_type = cat->getPreferredType(); + } + } + return LLFolderBridge::getIcon(preferred_type); +} + +void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + // *TODO: Translate + lldebugs << "LLLink::buildContextMenu()" << llendl; + std::vector<std::string> items; + std::vector<std::string> disabled_items; + + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Goto Link")); + items.push_back(std::string("Delete")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Delete")); + } + } + hide_context_entries(menu, items, disabled_items); +} + +void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("goto" == action) + { + gotoItem(folder); + return; + } + LLItemBridge::performAction(folder,model,action); +} + +void LLLinkFolderBridge::gotoItem(LLFolderView *folder) +{ + const LLUUID &cat_uuid = getFolderID(); + if (!cat_uuid.isNull()) + { + if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid)) + { + if (LLInventoryModel* model = getInventoryModel()) + { + model->fetchDescendentsOf(cat_uuid); + } + base_folder->setOpen(TRUE); + folder->setSelectionFromRoot(base_folder,TRUE); + folder->scrollToShowSelection(); + } + } +} + +const LLUUID &LLLinkFolderBridge::getFolderID() const +{ + if (LLViewerInventoryItem *link_item = getItem()) + { + if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory()) + { + const LLUUID& cat_uuid = cat->getUUID(); + return cat_uuid; + } + } + return LLUUID::null; +} diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 69214b5cab..a16ffe19c6 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -36,6 +36,8 @@ #include "llappviewer.h" #include "llfloaterchat.h" #include "lltrans.h" +#include "llviewercontrol.h" +#include "llsdserialize.h" const S32 LOG_RECALL_SIZE = 2048; @@ -89,41 +91,53 @@ std::string LLLogChat::timestamp(bool withdate) //static -void LLLogChat::saveHistory(std::string filename, std::string line) +void LLLogChat::saveHistory(const std::string& filename, + const std::string& from, + const LLUUID& from_id, + const std::string& line) { + if (!gSavedPerAccountSettings.getBOOL("LogInstantMessages")) + return; + if(!filename.size()) { llinfos << "Filename is Empty!" << llendl; return; } - LLFILE* fp = LLFile::fopen(LLLogChat::makeLogFileName(filename), "a"); /*Flawfinder: ignore*/ - if (!fp) + llofstream file (LLLogChat::makeLogFileName(filename), std::ios_base::app); + if (!file.is_open()) { llinfos << "Couldn't open chat history log!" << llendl; + return; } - else - { - fprintf(fp, "%s\n", line.c_str()); - - fclose (fp); - } + + LLSD item; + + if (gSavedPerAccountSettings.getBOOL("LogTimestamp")) + item["time"] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")); + + item["from"] = from; + item["from_id"] = from_id; + item["message"] = line; + + file << LLSDOStreamer <LLSDNotationFormatter>(item) << std::endl; + + file.close(); } -void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType,std::string,void*), void* userdata) +void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata) { if(!filename.size()) { llwarns << "Filename is Empty!" << llendl; return ; } - + LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r"); /*Flawfinder: ignore*/ if (!fptr) { - //LLUIString message = LLTrans::getString("IM_logging_string"); - //callback(LOG_EMPTY,"IM_logging_string",userdata); - callback(LOG_EMPTY,LLStringUtil::null,userdata); + callback(LOG_EMPTY, LLSD(), userdata); return; //No previous conversation with this name. } else @@ -143,6 +157,9 @@ void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType } } + // the parser's destructor is protected so we cannot create in the stack. + LLPointer<LLSDParser> parser = new LLSDNotationParser(); + while ( fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr) ) { len = strlen(buffer) - 1; /*Flawfinder: ignore*/ @@ -150,14 +167,25 @@ void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType if (!firstline) { - callback(LOG_LINE,std::string(buffer),userdata); + LLSD item; + std::string line(buffer); + std::istringstream iss(line); + if (parser->parse(iss, item, line.length()) == LLSDParser::PARSE_FAILURE) + { + item["message"] = line; + callback(LOG_LINE, item, userdata); + } + else + { + callback(LOG_LLSD, item, userdata); + } } else { firstline = FALSE; } } - callback(LOG_END,LLStringUtil::null,userdata); + callback(LOG_END, LLSD(), userdata); fclose(fptr); } diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index ad903b66fe..e252cd7d41 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -41,13 +41,18 @@ public: enum ELogLineType { LOG_EMPTY, LOG_LINE, + LOG_LLSD, LOG_END }; static std::string timestamp(bool withdate = false); static std::string makeLogFileName(std::string(filename)); - static void saveHistory(std::string filename, std::string line); - static void loadHistory(std::string filename, - void (*callback)(ELogLineType,std::string,void*), + static void saveHistory(const std::string& filename, + const std::string& from, + const LLUUID& from_id, + const std::string& line); + + static void loadHistory(const std::string& filename, + void (*callback)(ELogLineType, const LLSD&, void*), void* userdata); private: static std::string cleanFileName(std::string filename); diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 2b4e35208a..14da35594f 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -280,6 +280,14 @@ void LLFloaterMove::setMovementMode(const EMovementMode mode) mCurrentMode = mode; gAgent.setFlying(MM_FLY == mode); + // attempts to set avatar flying can not set it real flying in some cases. + // For ex. when avatar fell down & is standing up. + // So, no need to continue processing FLY mode. See EXT-1079 + if (MM_FLY == mode && !gAgent.getFlying()) + { + return; + } + switch (mode) { case MM_RUN: diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index ff7f08bf97..36cf2c1aa8 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -65,7 +65,6 @@ #include "llworld.h" //for particle system banning #include "llchat.h" #include "llfloaterchat.h" -#include "llimpanel.h" #include "llimview.h" #include "llnotifications.h" #include "lluistring.h" diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index c32ef2f22b..e63daac4af 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -164,8 +164,6 @@ TODO: - Load navbar height from saved settings (as it's done for status bar) or think of a better way. */ -S32 NAVIGATION_BAR_HEIGHT = 60; // *HACK, used in llviewerwindow.cpp - LLNavigationBar::LLNavigationBar() : mTeleportHistoryMenu(NULL), mBtnBack(NULL), @@ -519,8 +517,8 @@ void LLNavigationBar::showTeleportHistoryMenu() // *TODO: why to draw/update anything before showing the menu? mTeleportHistoryMenu->buildDrawLabels(); mTeleportHistoryMenu->updateParent(LLMenuGL::sMenuContainer); - LLRect btnBackRect = mBtnBack->getRect(); - LLMenuGL::showPopup(this, mTeleportHistoryMenu, btnBackRect.mLeft, btnBackRect.mBottom); + const S32 MENU_SPAWN_PAD = -1; + LLMenuGL::showPopup(mBtnBack, mTeleportHistoryMenu, 0, MENU_SPAWN_PAD); // *HACK pass the mouse capturing to the drop-down menu gFocusMgr.setMouseCapture( NULL ); @@ -545,6 +543,15 @@ void LLNavigationBar::clearHistoryCache() mPurgeTPHistoryItems= true; } +int LLNavigationBar::getDefNavBarHeight() +{ + return mDefaultNbRect.getHeight(); +} +int LLNavigationBar::getDefFavBarHeight() +{ + return mDefaultFpRect.getHeight(); +} + void LLNavigationBar::showNavigationPanel(BOOL visible) { bool fpVisible = gSavedSettings.getBOOL("ShowNavbarFavoritesPanel"); diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index f1a1b85a86..8b625e7fa6 100644 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -35,8 +35,6 @@ #include "llpanel.h" -extern S32 NAVIGATION_BAR_HEIGHT; - class LLButton; class LLLocationInputCtrl; class LLMenuGL; @@ -63,6 +61,9 @@ public: void showNavigationPanel(BOOL visible); void showFavoritesPanel(BOOL visible); + + int getDefNavBarHeight(); + int getDefFavBarHeight(); private: diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 217007fb15..32dc5e5927 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -224,7 +224,6 @@ BOOL LLNearbyChatBar::postBuild() mChatBox->setIgnoreTab(TRUE); mChatBox->setPassDelete(TRUE); mChatBox->setReplaceNewlinesWithSpaces(FALSE); - mChatBox->setMaxTextLength(1023); mChatBox->setEnableLineHistory(TRUE); mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 6b0d6d61e0..957513e154 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -162,6 +162,8 @@ bool LLNearbyChatScreenChannel::createPoolToast() LLToast::Params p; p.panel = panel; + p.lifetime_secs = gSavedSettings.getS32("NearbyToastLifeTime"); + p.fading_time_secs = gSavedSettings.getS32("NearbyToastFadingTime"); LLToast* toast = new LLToast(p); @@ -326,6 +328,12 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg) initChannel(); } + //only messages from AGENTS + if(CHAT_SOURCE_OBJECT == chat_msg.mSourceType) + { + return;//dn't show toast for messages from objects + } + LLUUID id; id.generate(); diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 7bc42b36f9..78aa04762d 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -1,955 +1,958 @@ -/**
- * @file llpanellandmarks.cpp
- * @brief Landmarks tab for Side Bar "Places" panel
- *
- * $LicenseInfo:firstyear=2009&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 "llpanellandmarks.h"
-
-#include "llbutton.h"
-#include "llfloaterreg.h"
-#include "llsdutil.h"
-#include "llsdutil_math.h"
-
-#include "llaccordionctrl.h"
-#include "llaccordionctrltab.h"
-#include "llagent.h"
-#include "llagentpicksinfo.h"
-#include "llagentui.h"
-#include "llcallbacklist.h"
-#include "lldndbutton.h"
-#include "llfloaterworldmap.h"
-#include "llfolderviewitem.h"
-#include "llinventorypanel.h"
-#include "llinventorysubtreepanel.h"
-#include "lllandmarkactions.h"
-#include "llplacesinventorybridge.h"
-#include "llsidetray.h"
-#include "llviewermenu.h"
-#include "llviewerregion.h"
-
-// Not yet implemented; need to remove buildPanel() from constructor when we switch
-//static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks");
-
-static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn";
-static const std::string ADD_BUTTON_NAME = "add_btn";
-static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn";
-static const std::string TRASH_BUTTON_NAME = "trash_btn";
-
-
-// helper functions
-static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string);
-
-
-LLLandmarksPanel::LLLandmarksPanel()
- : LLPanelPlacesTab()
- , mFavoritesInventoryPanel(NULL)
- , mLandmarksInventoryPanel(NULL)
- , mMyInventoryPanel(NULL)
- , mLibraryInventoryPanel(NULL)
- , mCurrentSelectedList(NULL)
- , mListCommands(NULL)
- , mGearFolderMenu(NULL)
- , mGearLandmarkMenu(NULL)
- , mDirtyFilter(false)
-{
- LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml");
-}
-
-LLLandmarksPanel::~LLLandmarksPanel()
-{
-}
-
-BOOL LLLandmarksPanel::postBuild()
-{
- if (!gInventory.isInventoryUsable())
- return FALSE;
-
- // mast be called before any other initXXX methods to init Gear menu
- initListCommandsHandlers();
-
- U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER);
- mSortByDate = sort_order & LLInventoryFilter::SO_DATE;
- initFavoritesInventroyPanel();
- initLandmarksInventroyPanel();
- initMyInventroyPanel();
- initLibraryInventroyPanel();
-
- gIdleCallbacks.addFunction(LLLandmarksPanel::doIdle, this);
- return TRUE;
-}
-
-// virtual
-void LLLandmarksPanel::onSearchEdit(const std::string& string)
-{
- static std::string prev_string("");
-
- if (prev_string == string) return;
-
- // show all folders in Landmarks Accordion for empty filter
- mLandmarksInventoryPanel->setShowFolderState(string.empty() ?
- LLInventoryFilter::SHOW_ALL_FOLDERS :
- LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS
- );
-
- filter_list(mFavoritesInventoryPanel, string);
- filter_list(mLandmarksInventoryPanel, string);
- filter_list(mMyInventoryPanel, string);
- filter_list(mLibraryInventoryPanel, string);
-
- prev_string = string;
- mDirtyFilter = true;
-
- // 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)
- {
- LLAccordionCtrlTab* tab = *iter;
- tab->setVisible(true);
- }
-}
-
-// virtual
-void LLLandmarksPanel::onShowOnMap()
-{
- if (NULL == mCurrentSelectedList)
- {
- llwarns << "There are no selected list. No actions are performed." << llendl;
- return;
- }
- LLLandmark* landmark = getCurSelectedLandmark();
- if (!landmark)
- return;
-
- LLVector3d landmark_global_pos;
- if (!landmark->getGlobalPos(landmark_global_pos))
- return;
-
- LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
- if (!landmark_global_pos.isExactlyZero() && worldmap_instance)
- {
- worldmap_instance->trackLocation(landmark_global_pos);
- LLFloaterReg::showInstance("world_map", "center");
- }
-}
-
-// virtual
-void LLLandmarksPanel::onTeleport()
-{
- LLFolderViewItem* current_item = getCurSelectedItem();
- if (!current_item)
- {
- llwarns << "There are no selected list. No actions are performed." << llendl;
- return;
- }
-
- LLFolderViewEventListener* listenerp = current_item->getListener();
- if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
- {
- listenerp->openItem();
- }
-}
-
-// virtual
-void LLLandmarksPanel::updateVerbs()
-{
- if (!isTabVisible())
- return;
-
- BOOL enabled = isLandmarkSelected();
- mTeleportBtn->setEnabled(enabled);
- mShowOnMapBtn->setEnabled(enabled);
-
- // TODO: mantipov: Uncomment when mShareBtn is supported
- // Share button should be enabled when neither a folder nor a landmark is selected
- //mShareBtn->setEnabled(NULL != current_item);
-
- updateListCommands();
-}
-
-void LLLandmarksPanel::onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
-{
- if (user_action && (items.size() > 0))
- {
- deselectOtherThan(inventory_list);
- mCurrentSelectedList = inventory_list;
- }
-
- LLFolderViewItem* current_item = inventory_list->getRootFolder()->getCurSelectedItem();
- if (!current_item)
- return;
-
- updateVerbs();
-}
-
-void LLLandmarksPanel::onSelectorButtonClicked()
-{
- // TODO: mantipov: update getting of selected item
- // TODO: bind to "i" button
- LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem();
-
- LLFolderViewEventListener* listenerp = cur_item->getListener();
- if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
- {
- LLSD key;
- key["type"] = "landmark";
- key["id"] = listenerp->getUUID();
-
- LLSideTray::getInstance()->showPanel("panel_places", key);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-// PROTECTED METHODS
-//////////////////////////////////////////////////////////////////////////
-
-bool LLLandmarksPanel::isLandmarkSelected() const
-{
- LLFolderViewItem* current_item = getCurSelectedItem();
- if(current_item && current_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
- {
- return true;
- }
-
- return false;
-}
-
-bool LLLandmarksPanel::isReceivedFolderSelected() const
-{
- // Received Folder can be only in Landmarks accordion
- if (mCurrentSelectedList != mLandmarksInventoryPanel) return false;
-
- // *TODO: it should be filled with logic when EXT-976 is done.
-
- llwarns << "Not implemented yet until EXT-976 is done." << llendl;
-
- return false;
-}
-LLLandmark* LLLandmarksPanel::getCurSelectedLandmark() const
-{
-
- LLFolderViewItem* cur_item = getCurSelectedItem();
- if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
- {
- return LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID());
- }
- return NULL;
-}
-
-LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem () const
-{
- return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;
-}
-
-void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate)
-{
- if(!panel) return;
-
- U32 order = panel->getSortOrder();
- if (byDate)
- {
- panel->setSortOrder( order | LLInventoryFilter::SO_DATE );
- }
- else
- {
- panel->setSortOrder( order & ~LLInventoryFilter::SO_DATE );
- }
-}
-
-// virtual
-void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)
-{
- //this function will be called after user will try to create a pick for selected landmark.
- // We have to make request to sever to get parcel_id and snaption_id.
- if(isLandmarkSelected())
- {
- LLLandmark* landmark = getCurSelectedLandmark();
- LLFolderViewItem* cur_item = getCurSelectedItem();
- LLUUID id = cur_item->getListener()->getUUID();
- LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id);
- if(landmark)
- {
- LLPanelPickEdit* panel_pick = LLPanelPickEdit::create();
- LLVector3d landmark_global_pos;
- landmark->getGlobalPos(landmark_global_pos);
-
- // let's toggle pick panel into panel places
- LLPanel* panel_places = LLSideTray::getInstance()->getChild<LLPanel>("panel_places");//-> sidebar_places
- panel_places->addChild(panel_pick);
- LLRect paren_rect(panel_places->getRect());
- panel_pick->reshape(paren_rect.getWidth(),paren_rect.getHeight(), TRUE);
- panel_pick->setRect(paren_rect);
- panel_pick->onOpen(LLSD());
-
- LLPickData data;
- data.pos_global = landmark_global_pos;
- data.name = cur_item->getName();
- data.desc = inv_item->getDescription();
- data.snapshot_id = parcel_data.snapshot_id;
- data.parcel_id = parcel_data.parcel_id;
- panel_pick->setPickData(&data);
-
- LLSD params;
- params["parcel_id"] =parcel_data.parcel_id;
- /* set exit callback to get back onto panel places
- in callback we will make cleaning up( delete pick_panel instance,
- remove landmark panel from observer list
- */
- panel_pick->setExitCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
- panel_pick, panel_places,params));
- panel_pick->setSaveCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
- panel_pick, panel_places,params));
- panel_pick->setCancelCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
- panel_pick, panel_places,params));
- }
- }
-}
-
-// virtual
-void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id)
-{
- if (!parcel_id.isNull())
- {
- LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
- LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
- }
-}
-
-// virtual
-void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)
-{
- llerrs<< "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-// PRIVATE METHODS
-//////////////////////////////////////////////////////////////////////////
-
-void LLLandmarksPanel::initFavoritesInventroyPanel()
-{
- mFavoritesInventoryPanel = getChild<LLInventorySubTreePanel>("favorites_list");
-
- initLandmarksPanel(mFavoritesInventoryPanel);
-
- initAccordion("tab_favorites", mFavoritesInventoryPanel);
-}
-
-void LLLandmarksPanel::initLandmarksInventroyPanel()
-{
- mLandmarksInventoryPanel = getChild<LLInventorySubTreePanel>("landmarks_list");
-
- initLandmarksPanel(mLandmarksInventoryPanel);
-
- mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);
-
- // subscribe to have auto-rename functionality while creating New Folder
- mLandmarksInventoryPanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mLandmarksInventoryPanel, _1, _2));
-
- initAccordion("tab_landmarks", mLandmarksInventoryPanel);
-}
-
-void LLLandmarksPanel::initMyInventroyPanel()
-{
- mMyInventoryPanel= getChild<LLInventorySubTreePanel>("my_inventory_list");
-
- initLandmarksPanel(mMyInventoryPanel);
-
- initAccordion("tab_inventory", mMyInventoryPanel);
-}
-
-void LLLandmarksPanel::initLibraryInventroyPanel()
-{
- mLibraryInventoryPanel = getChild<LLInventorySubTreePanel>("library_list");
-
- initLandmarksPanel(mLibraryInventoryPanel);
-
- initAccordion("tab_library", mLibraryInventoryPanel);
-}
-
-void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_list)
-{
- inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK);
- inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2));
-
- inventory_list->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
- updateSortOrder(inventory_list, mSortByDate);
-
- LLPlacesFolderView* root_folder = dynamic_cast<LLPlacesFolderView*>(inventory_list->getRootFolder());
- if (root_folder)
- {
- root_folder->setupMenuHandle(LLInventoryType::IT_CATEGORY, mGearFolderMenu->getHandle());
- root_folder->setupMenuHandle(LLInventoryType::IT_LANDMARK, mGearLandmarkMenu->getHandle());
- }
-
- // save initial folder state to avoid incorrect work while switching between Landmarks & Teleport History tabs
- // See EXT-1609.
- inventory_list->saveFolderState();
-}
-
-void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list)
-{
- LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name);
- mAccordionTabs.push_back(accordion_tab);
- accordion_tab->setDropDownStateChangedCallback(
- boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list));
-}
-
-void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list)
-{
- bool expanded = param.asBoolean();
-
- if(!expanded && (mCurrentSelectedList == inventory_list))
- {
- inventory_list->getRootFolder()->clearSelection();
-
- mCurrentSelectedList = NULL;
- updateVerbs();
- }
-}
-
-void LLLandmarksPanel::deselectOtherThan(const LLInventorySubTreePanel* inventory_list)
-{
- if (inventory_list != mFavoritesInventoryPanel)
- {
- mFavoritesInventoryPanel->getRootFolder()->clearSelection();
- }
-
- if (inventory_list != mLandmarksInventoryPanel)
- {
- mLandmarksInventoryPanel->getRootFolder()->clearSelection();
- }
- if (inventory_list != mMyInventoryPanel)
- {
- mMyInventoryPanel->getRootFolder()->clearSelection();
- }
- if (inventory_list != mLibraryInventoryPanel)
- {
- mLibraryInventoryPanel->getRootFolder()->clearSelection();
- }
-}
-
-// List Commands Handlers
-void LLLandmarksPanel::initListCommandsHandlers()
-{
- mListCommands = getChild<LLPanel>("bottom_panel");
-
- mListCommands->childSetAction(OPTIONS_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onActionsButtonClick, this));
- mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this));
- mListCommands->getChild<LLButton>(ADD_BUTTON_NAME)->setHeldDownCallback(boost::bind(&LLLandmarksPanel::onAddButtonHeldDown, this));
- static const LLSD add_landmark_command("add_landmark");
- mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddAction, this, add_landmark_command));
-
- LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>(TRASH_BUTTON_NAME);
- trash_btn->setDragAndDropHandler(boost::bind(&LLLandmarksPanel::handleDragAndDropToTrash, this
- , _4 // BOOL drop
- , _5 // EDragAndDropType cargo_type
- , _7 // EAcceptance* accept
- ));
-
- mCommitCallbackRegistrar.add("Places.LandmarksGear.Add.Action", boost::bind(&LLLandmarksPanel::onAddAction, this, _2));
- mCommitCallbackRegistrar.add("Places.LandmarksGear.CopyPaste.Action", boost::bind(&LLLandmarksPanel::onClipboardAction, this, _2));
- mCommitCallbackRegistrar.add("Places.LandmarksGear.Custom.Action", boost::bind(&LLLandmarksPanel::onCustomAction, this, _2));
- mCommitCallbackRegistrar.add("Places.LandmarksGear.Folding.Action", boost::bind(&LLLandmarksPanel::onFoldingAction, this, _2));
- mEnableCallbackRegistrar.add("Places.LandmarksGear.Check", boost::bind(&LLLandmarksPanel::isActionChecked, this, _2));
- mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2));
- mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-}
-
-
-void LLLandmarksPanel::updateListCommands()
-{
- bool add_folder_enabled = isActionEnabled("category");
- bool trash_enabled = isActionEnabled("delete");
-
- // keep Options & Add Landmark buttons always enabled
- mListCommands->childSetEnabled(ADD_FOLDER_BUTTON_NAME, add_folder_enabled);
- mListCommands->childSetEnabled(TRASH_BUTTON_NAME, trash_enabled);
-}
-
-void LLLandmarksPanel::onActionsButtonClick()
-{
- LLFolderViewItem* cur_item = NULL;
- if(mCurrentSelectedList)
- cur_item = mCurrentSelectedList->getRootFolder()->getCurSelectedItem();
-
- if(!cur_item)
- return;
-
- LLFolderViewEventListener* listenerp = cur_item->getListener();
-
- LLMenuGL* menu =NULL;
- if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
- {
- menu = mGearLandmarkMenu;
- }
- else if (listenerp->getInventoryType() == LLInventoryType::IT_CATEGORY)
- {
- mGearFolderMenu->getChild<LLMenuItemCallGL>("expand")->setVisible(!cur_item->isOpen());
- mGearFolderMenu->getChild<LLMenuItemCallGL>("collapse")->setVisible(cur_item->isOpen());
- menu = mGearFolderMenu;
- }
- showActionMenu(menu,OPTIONS_BUTTON_NAME);
-}
-
-void LLLandmarksPanel::onAddButtonHeldDown()
-{
- showActionMenu(mMenuAdd,ADD_BUTTON_NAME);
-}
-
-void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
-{
- if (menu)
- {
- menu->buildDrawLabels();
- menu->updateParent(LLMenuGL::sMenuContainer);
- LLView* spawning_view = getChild<LLView> (spawning_view_name);
- S32 menu_x, menu_y;
- //show menu in co-ordinates of panel
- spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
- menu_y += menu->getRect().getHeight();
- LLMenuGL::showPopup(this, menu, menu_x, menu_y);
- }
-}
-
-void LLLandmarksPanel::onTrashButtonClick() const
-{
- onClipboardAction("delete");
-}
-
-void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
-{
- std::string command_name = userdata.asString();
- if("add_landmark" == command_name)
- {
- if(LLLandmarkActions::landmarkAlreadyExists())
- {
- std::string location;
- LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_FULL);
- llwarns<<" Landmark already exists at location: "<< location<<llendl;
- return;
- }
- LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark"));
- }
- else if ("category" == command_name)
- {
- LLFolderViewItem* item = getCurSelectedItem();
- if (item && mCurrentSelectedList == mLandmarksInventoryPanel)
- {
- LLFolderViewEventListener* folder_bridge = NULL;
- if (item-> getListener()->getInventoryType()
- == LLInventoryType::IT_LANDMARK)
- {
- // for a landmark get parent folder bridge
- folder_bridge = item->getParentFolder()->getListener();
- }
- else if (item-> getListener()->getInventoryType()
- == LLInventoryType::IT_CATEGORY)
- {
- // for a folder get its own bridge
- folder_bridge = item->getListener();
- }
-
- menu_create_inventory_item(mCurrentSelectedList->getRootFolder(),
- dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD(
- "category"), gInventory.findCategoryUUIDForType(
- LLAssetType::AT_LANDMARK));
- }
- }
-}
-
-void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const
-{
- if(!mCurrentSelectedList)
- return;
- std::string command_name = userdata.asString();
- if("copy_slurl" == command_name)
- {
- LLFolderViewItem* cur_item = getCurSelectedItem();
- if(cur_item)
- LLLandmarkActions::copySLURLtoClipboard(cur_item->getListener()->getUUID());
- }
- else if ( "paste" == command_name)
- {
- mCurrentSelectedList->getRootFolder()->paste();
- }
- else if ( "cut" == command_name)
- {
- mCurrentSelectedList->getRootFolder()->cut();
- }
- else
- {
- mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(),command_name);
- }
-}
-
-void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)
-{
- if(!mCurrentSelectedList) return;
-
- LLFolderView* root_folder = mCurrentSelectedList->getRootFolder();
- std::string command_name = userdata.asString();
-
- if ("expand_all" == command_name)
- {
- root_folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN);
- root_folder->arrangeAll();
- }
- else if ("collapse_all" == command_name)
- {
- root_folder->closeAllFolders();
- }
- else if ( "sort_by_date" == command_name)
- {
- mSortByDate = !mSortByDate;
- updateSortOrder(mLandmarksInventoryPanel, mSortByDate);
- updateSortOrder(mMyInventoryPanel, mSortByDate);
- updateSortOrder(mLibraryInventoryPanel, mSortByDate);
- }
- else
- {
- root_folder->doToSelected(&gInventory, userdata);
- }
-}
-
-bool LLLandmarksPanel::isActionChecked(const LLSD& userdata) const
-{
- const std::string command_name = userdata.asString();
-
- if ( "sort_by_date" == command_name)
- {
- return mSortByDate;
- }
-
- return false;
-}
-
-bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
-{
- std::string command_name = userdata.asString();
-
-
- LLPlacesFolderView* rootFolderView = mCurrentSelectedList ?
- static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()) : NULL;
-
- if (NULL == rootFolderView) return false;
-
- // disable some commands for multi-selection. EXT-1757
- if (rootFolderView->getSelectedCount() > 1)
- {
- if ( "teleport" == command_name
- || "more_info" == command_name
- || "rename" == command_name
- || "show_on_map" == command_name
- || "copy_slurl" == command_name
- )
- {
- return false;
- }
-
- }
-
- // disable some commands for Favorites accordion. EXT-1758
- if (mCurrentSelectedList == mFavoritesInventoryPanel)
- {
- if ( "expand_all" == command_name
- || "collapse_all" == command_name
- || "sort_by_date" == command_name
- )
- return false;
- }
-
-
- if("category" == command_name)
- {
- // we can add folder only in Landmarks Accordion
- if (mCurrentSelectedList == mLandmarksInventoryPanel)
- {
- // ... but except Received folder
- return !isReceivedFolderSelected();
- }
- else return false;
- }
- else if("paste" == command_name || "rename" == command_name || "cut" == command_name || "delete" == command_name)
- {
- return canSelectedBeModified(command_name);
- }
- else if ( "sort_by_date" == command_name)
- {
- return mSortByDate;
- }
- else if("create_pick" == command_name)
- {
- return !LLAgentPicksInfo::getInstance()->isPickLimitReached();
- }
- else
- {
- llwarns << "Unprocessed command has come: " << command_name << llendl;
- }
-
- return true;
-}
-
-void LLLandmarksPanel::onCustomAction(const LLSD& userdata)
-{
- LLFolderViewItem* cur_item = getCurSelectedItem();
- if(!cur_item)
- return ;
- std::string command_name = userdata.asString();
- if("more_info" == command_name)
- {
- cur_item->getListener()->performAction(mCurrentSelectedList->getRootFolder(),mCurrentSelectedList->getModel(),"about");
- }
- else if ("teleport" == command_name)
- {
- onTeleport();
- }
- else if ("show_on_map" == command_name)
- {
- onShowOnMap();
- }
- else if ("create_pick" == command_name)
- {
- LLLandmark* landmark = getCurSelectedLandmark();
- if(!landmark) return;
-
- LLViewerRegion* region = gAgent.getRegion();
- if (!region) return;
-
- LLGlobalVec pos_global;
- LLUUID region_id;
- landmark->getGlobalPos(pos_global);
- landmark->getRegionID(region_id);
- LLVector3 region_pos((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS),
- (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS),
- (F32)pos_global.mdV[VZ]);
-
- LLSD body;
- std::string url = region->getCapability("RemoteParcelRequest");
- if (!url.empty())
- {
- body["location"] = ll_sd_from_vector3(region_pos);
- 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 create pick for landmark for region" << region_id
- << ". Region: " << region->getName()
- << " does not support RemoteParcelRequest" << llendl;
- }
- }
-}
-
-/*
-Processes such actions: cut/rename/delete/paste actions
-
-Rules:
- 1. We can't perform any action in Library
- 2. For Landmarks we can:
- - cut/rename/delete in any other accordions
- - paste - only in Favorites, Landmarks accordions
- 3. For Folders we can: perform any action in Landmarks accordion, except Received folder
- 4. We can not paste folders from Clipboard (processed by LLFolderView::canPaste())
- 5. Check LLFolderView/Inventory Bridges rules
- */
-bool LLLandmarksPanel::canSelectedBeModified(const std::string& command_name) const
-{
- // validate own rules first
-
- // nothing can be modified in Library
- if (mLibraryInventoryPanel == mCurrentSelectedList) return false;
-
- bool can_be_modified = false;
-
- // landmarks can be modified in any other accordion...
- if (isLandmarkSelected())
- {
- can_be_modified = true;
-
- // we can modify landmarks anywhere except paste to My Inventory
- if ("paste" == command_name)
- {
- can_be_modified = (mCurrentSelectedList != mMyInventoryPanel);
- }
- }
- else
- {
- // ...folders only in the Landmarks accordion...
- can_be_modified = mLandmarksInventoryPanel == mCurrentSelectedList;
-
- // ...except "Received" folder
- can_be_modified &= !isReceivedFolderSelected();
- }
-
- // then ask LLFolderView permissions
- if (can_be_modified)
- {
- if ("cut" == command_name)
- {
- can_be_modified = mCurrentSelectedList->getRootFolder()->canCut();
- }
- else if ("rename" == command_name)
- {
- can_be_modified = getCurSelectedItem()->getListener()->isItemRenameable();
- }
- else if ("delete" == command_name)
- {
- can_be_modified = getCurSelectedItem()->getListener()->isItemRemovable();
- }
- else if("paste" == command_name)
- {
- return mCurrentSelectedList->getRootFolder()->canPaste();
- }
- else
- {
- llwarns << "Unprocessed command has come: " << command_name << llendl;
- }
- }
-
- return can_be_modified;
-}
-
-void LLLandmarksPanel::onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params)
-{
- pick_panel->setVisible(FALSE);
- owner->removeChild(pick_panel);
- //we need remove observer to avoid processParcelInfo in the future.
- LLRemoteParcelInfoProcessor::getInstance()->removeObserver(params["parcel_id"].asUUID(), this);
-
- delete pick_panel;
- pick_panel = NULL;
-}
-
-bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept)
-{
- *accept = ACCEPT_NO;
-
- switch (cargo_type)
- {
-
- case DAD_LANDMARK:
- case DAD_CATEGORY:
- {
- bool is_enabled = isActionEnabled("delete");
-
- if (is_enabled) *accept = ACCEPT_YES_MULTI;
-
- if (is_enabled && drop)
- {
- onClipboardAction("delete");
- }
- }
- break;
- default:
- break;
- }
-
- return true;
-}
-
-
-void LLLandmarksPanel::doIdle(void* landmarks_panel)
-{
- LLLandmarksPanel* panel = (LLLandmarksPanel* ) landmarks_panel;
-
- if (panel->mDirtyFilter)
- {
- panel->updateFilteredAccordions();
- }
-
-}
-
-void LLLandmarksPanel::updateFilteredAccordions()
-{
- LLInventoryPanel* inventory_list = NULL;
- LLAccordionCtrlTab* accordion_tab = NULL;
- for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
- {
- accordion_tab = *iter;
- inventory_list = dynamic_cast<LLInventorySubTreePanel*> (accordion_tab->getAccordionView());
- if (NULL == inventory_list) continue;
- LLFolderView* fv = inventory_list->getRootFolder();
-
- bool has_visible_children = fv->hasVisibleChildren();
-
- accordion_tab->setVisible(has_visible_children);
- }
-
- // we have to arrange accordion tabs for cases when filter string is less restrictive but
- // all items are still filtered.
- static LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
- accordion->arrange();
-
- // now filter state is applied to accordion tabs
- mDirtyFilter = false;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-// HELPER FUNCTIONS
-//////////////////////////////////////////////////////////////////////////
-static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string)
-{
- if (string == "")
- {
- inventory_list->setFilterSubString(LLStringUtil::null);
-
- // re-open folders that were initially open
- inventory_list->restoreFolderState();
- }
-
- gInventory.startBackgroundFetch();
-
- if (inventory_list->getFilterSubString().empty() && string.empty())
- {
- // current filter and new filter empty, do nothing
- return;
- }
-
- // save current folder open state if no filter currently applied
- if (inventory_list->getRootFolder()->getFilterSubString().empty())
- {
- inventory_list->saveFolderState();
- }
-
- // set new filter string
- inventory_list->setFilterSubString(string);
-}
-// EOF
+/** + * @file llpanellandmarks.cpp + * @brief Landmarks tab for Side Bar "Places" panel + * + * $LicenseInfo:firstyear=2009&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 "llpanellandmarks.h" + +#include "llbutton.h" +#include "llfloaterreg.h" +#include "llsdutil.h" +#include "llsdutil_math.h" + +#include "llaccordionctrl.h" +#include "llaccordionctrltab.h" +#include "llagent.h" +#include "llagentpicksinfo.h" +#include "llagentui.h" +#include "llcallbacklist.h" +#include "lldndbutton.h" +#include "llfloaterworldmap.h" +#include "llfolderviewitem.h" +#include "llinventorypanel.h" +#include "llinventorysubtreepanel.h" +#include "lllandmarkactions.h" +#include "llplacesinventorybridge.h" +#include "llsidetray.h" +#include "llviewermenu.h" +#include "llviewerregion.h" + +// Not yet implemented; need to remove buildPanel() from constructor when we switch +//static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks"); + +static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn"; +static const std::string ADD_BUTTON_NAME = "add_btn"; +static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn"; +static const std::string TRASH_BUTTON_NAME = "trash_btn"; + + +// helper functions +static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string); + + +LLLandmarksPanel::LLLandmarksPanel() + : LLPanelPlacesTab() + , mFavoritesInventoryPanel(NULL) + , mLandmarksInventoryPanel(NULL) + , mMyInventoryPanel(NULL) + , mLibraryInventoryPanel(NULL) + , mCurrentSelectedList(NULL) + , mListCommands(NULL) + , mGearFolderMenu(NULL) + , mGearLandmarkMenu(NULL) + , mDirtyFilter(false) +{ + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml"); +} + +LLLandmarksPanel::~LLLandmarksPanel() +{ +} + +BOOL LLLandmarksPanel::postBuild() +{ + if (!gInventory.isInventoryUsable()) + return FALSE; + + // mast be called before any other initXXX methods to init Gear menu + initListCommandsHandlers(); + + U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER); + mSortByDate = sort_order & LLInventoryFilter::SO_DATE; + initFavoritesInventroyPanel(); + initLandmarksInventroyPanel(); + initMyInventroyPanel(); + initLibraryInventroyPanel(); + + gIdleCallbacks.addFunction(LLLandmarksPanel::doIdle, this); + return TRUE; +} + +// virtual +void LLLandmarksPanel::onSearchEdit(const std::string& string) +{ + static std::string prev_string(""); + + if (prev_string == string) return; + + // show all folders in Landmarks Accordion for empty filter + mLandmarksInventoryPanel->setShowFolderState(string.empty() ? + LLInventoryFilter::SHOW_ALL_FOLDERS : + LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS + ); + + filter_list(mFavoritesInventoryPanel, string); + filter_list(mLandmarksInventoryPanel, string); + filter_list(mMyInventoryPanel, string); + filter_list(mLibraryInventoryPanel, string); + + prev_string = string; + mDirtyFilter = true; + + // 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) + { + LLAccordionCtrlTab* tab = *iter; + tab->setVisible(true); + + // expand accordion to see matched items in all ones. See EXT-2014. + tab->changeOpenClose(false); + } +} + +// virtual +void LLLandmarksPanel::onShowOnMap() +{ + if (NULL == mCurrentSelectedList) + { + llwarns << "There are no selected list. No actions are performed." << llendl; + return; + } + LLLandmark* landmark = getCurSelectedLandmark(); + if (!landmark) + return; + + LLVector3d landmark_global_pos; + if (!landmark->getGlobalPos(landmark_global_pos)) + return; + + LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); + if (!landmark_global_pos.isExactlyZero() && worldmap_instance) + { + worldmap_instance->trackLocation(landmark_global_pos); + LLFloaterReg::showInstance("world_map", "center"); + } +} + +// virtual +void LLLandmarksPanel::onTeleport() +{ + LLFolderViewItem* current_item = getCurSelectedItem(); + if (!current_item) + { + llwarns << "There are no selected list. No actions are performed." << llendl; + return; + } + + LLFolderViewEventListener* listenerp = current_item->getListener(); + if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) + { + listenerp->openItem(); + } +} + +// virtual +void LLLandmarksPanel::updateVerbs() +{ + if (!isTabVisible()) + return; + + BOOL enabled = isLandmarkSelected(); + mTeleportBtn->setEnabled(enabled); + mShowOnMapBtn->setEnabled(enabled); + + // TODO: mantipov: Uncomment when mShareBtn is supported + // Share button should be enabled when neither a folder nor a landmark is selected + //mShareBtn->setEnabled(NULL != current_item); + + updateListCommands(); +} + +void LLLandmarksPanel::onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action) +{ + if (user_action && (items.size() > 0)) + { + deselectOtherThan(inventory_list); + mCurrentSelectedList = inventory_list; + } + + LLFolderViewItem* current_item = inventory_list->getRootFolder()->getCurSelectedItem(); + if (!current_item) + return; + + updateVerbs(); +} + +void LLLandmarksPanel::onSelectorButtonClicked() +{ + // TODO: mantipov: update getting of selected item + // TODO: bind to "i" button + LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem(); + + LLFolderViewEventListener* listenerp = cur_item->getListener(); + if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) + { + LLSD key; + key["type"] = "landmark"; + key["id"] = listenerp->getUUID(); + + LLSideTray::getInstance()->showPanel("panel_places", key); + } +} + +////////////////////////////////////////////////////////////////////////// +// PROTECTED METHODS +////////////////////////////////////////////////////////////////////////// + +bool LLLandmarksPanel::isLandmarkSelected() const +{ + LLFolderViewItem* current_item = getCurSelectedItem(); + if(current_item && current_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) + { + return true; + } + + return false; +} + +bool LLLandmarksPanel::isReceivedFolderSelected() const +{ + // Received Folder can be only in Landmarks accordion + if (mCurrentSelectedList != mLandmarksInventoryPanel) return false; + + // *TODO: it should be filled with logic when EXT-976 is done. + + llwarns << "Not implemented yet until EXT-976 is done." << llendl; + + return false; +} +LLLandmark* LLLandmarksPanel::getCurSelectedLandmark() const +{ + + LLFolderViewItem* cur_item = getCurSelectedItem(); + if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) + { + return LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID()); + } + return NULL; +} + +LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem () const +{ + return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL; +} + +void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate) +{ + if(!panel) return; + + U32 order = panel->getSortOrder(); + if (byDate) + { + panel->setSortOrder( order | LLInventoryFilter::SO_DATE ); + } + else + { + panel->setSortOrder( order & ~LLInventoryFilter::SO_DATE ); + } +} + +// virtual +void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data) +{ + //this function will be called after user will try to create a pick for selected landmark. + // We have to make request to sever to get parcel_id and snaption_id. + if(isLandmarkSelected()) + { + LLLandmark* landmark = getCurSelectedLandmark(); + LLFolderViewItem* cur_item = getCurSelectedItem(); + LLUUID id = cur_item->getListener()->getUUID(); + LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id); + if(landmark) + { + LLPanelPickEdit* panel_pick = LLPanelPickEdit::create(); + LLVector3d landmark_global_pos; + landmark->getGlobalPos(landmark_global_pos); + + // let's toggle pick panel into panel places + LLPanel* panel_places = LLSideTray::getInstance()->getChild<LLPanel>("panel_places");//-> sidebar_places + panel_places->addChild(panel_pick); + LLRect paren_rect(panel_places->getRect()); + panel_pick->reshape(paren_rect.getWidth(),paren_rect.getHeight(), TRUE); + panel_pick->setRect(paren_rect); + panel_pick->onOpen(LLSD()); + + LLPickData data; + data.pos_global = landmark_global_pos; + data.name = cur_item->getName(); + data.desc = inv_item->getDescription(); + data.snapshot_id = parcel_data.snapshot_id; + data.parcel_id = parcel_data.parcel_id; + panel_pick->setPickData(&data); + + LLSD params; + params["parcel_id"] =parcel_data.parcel_id; + /* set exit callback to get back onto panel places + in callback we will make cleaning up( delete pick_panel instance, + remove landmark panel from observer list + */ + panel_pick->setExitCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, + panel_pick, panel_places,params)); + panel_pick->setSaveCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, + panel_pick, panel_places,params)); + panel_pick->setCancelCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, + panel_pick, panel_places,params)); + } + } +} + +// virtual +void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id) +{ + if (!parcel_id.isNull()) + { + LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this); + LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id); + } +} + +// virtual +void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason) +{ + llerrs<< "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl; +} + + +////////////////////////////////////////////////////////////////////////// +// PRIVATE METHODS +////////////////////////////////////////////////////////////////////////// + +void LLLandmarksPanel::initFavoritesInventroyPanel() +{ + mFavoritesInventoryPanel = getChild<LLInventorySubTreePanel>("favorites_list"); + + initLandmarksPanel(mFavoritesInventoryPanel); + + initAccordion("tab_favorites", mFavoritesInventoryPanel); +} + +void LLLandmarksPanel::initLandmarksInventroyPanel() +{ + mLandmarksInventoryPanel = getChild<LLInventorySubTreePanel>("landmarks_list"); + + initLandmarksPanel(mLandmarksInventoryPanel); + + mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + + // subscribe to have auto-rename functionality while creating New Folder + mLandmarksInventoryPanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mLandmarksInventoryPanel, _1, _2)); + + initAccordion("tab_landmarks", mLandmarksInventoryPanel); +} + +void LLLandmarksPanel::initMyInventroyPanel() +{ + mMyInventoryPanel= getChild<LLInventorySubTreePanel>("my_inventory_list"); + + initLandmarksPanel(mMyInventoryPanel); + + initAccordion("tab_inventory", mMyInventoryPanel); +} + +void LLLandmarksPanel::initLibraryInventroyPanel() +{ + mLibraryInventoryPanel = getChild<LLInventorySubTreePanel>("library_list"); + + initLandmarksPanel(mLibraryInventoryPanel); + + initAccordion("tab_library", mLibraryInventoryPanel); +} + +void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_list) +{ + inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK); + inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2)); + + inventory_list->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + updateSortOrder(inventory_list, mSortByDate); + + LLPlacesFolderView* root_folder = dynamic_cast<LLPlacesFolderView*>(inventory_list->getRootFolder()); + if (root_folder) + { + root_folder->setupMenuHandle(LLInventoryType::IT_CATEGORY, mGearFolderMenu->getHandle()); + root_folder->setupMenuHandle(LLInventoryType::IT_LANDMARK, mGearLandmarkMenu->getHandle()); + } + + // save initial folder state to avoid incorrect work while switching between Landmarks & Teleport History tabs + // See EXT-1609. + inventory_list->saveFolderState(); +} + +void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list) +{ + LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name); + mAccordionTabs.push_back(accordion_tab); + accordion_tab->setDropDownStateChangedCallback( + boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list)); +} + +void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list) +{ + bool expanded = param.asBoolean(); + + if(!expanded && (mCurrentSelectedList == inventory_list)) + { + inventory_list->getRootFolder()->clearSelection(); + + mCurrentSelectedList = NULL; + updateVerbs(); + } +} + +void LLLandmarksPanel::deselectOtherThan(const LLInventorySubTreePanel* inventory_list) +{ + if (inventory_list != mFavoritesInventoryPanel) + { + mFavoritesInventoryPanel->getRootFolder()->clearSelection(); + } + + if (inventory_list != mLandmarksInventoryPanel) + { + mLandmarksInventoryPanel->getRootFolder()->clearSelection(); + } + if (inventory_list != mMyInventoryPanel) + { + mMyInventoryPanel->getRootFolder()->clearSelection(); + } + if (inventory_list != mLibraryInventoryPanel) + { + mLibraryInventoryPanel->getRootFolder()->clearSelection(); + } +} + +// List Commands Handlers +void LLLandmarksPanel::initListCommandsHandlers() +{ + mListCommands = getChild<LLPanel>("bottom_panel"); + + mListCommands->childSetAction(OPTIONS_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onActionsButtonClick, this)); + mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this)); + mListCommands->getChild<LLButton>(ADD_BUTTON_NAME)->setHeldDownCallback(boost::bind(&LLLandmarksPanel::onAddButtonHeldDown, this)); + static const LLSD add_landmark_command("add_landmark"); + mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddAction, this, add_landmark_command)); + + LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>(TRASH_BUTTON_NAME); + trash_btn->setDragAndDropHandler(boost::bind(&LLLandmarksPanel::handleDragAndDropToTrash, this + , _4 // BOOL drop + , _5 // EDragAndDropType cargo_type + , _7 // EAcceptance* accept + )); + + mCommitCallbackRegistrar.add("Places.LandmarksGear.Add.Action", boost::bind(&LLLandmarksPanel::onAddAction, this, _2)); + mCommitCallbackRegistrar.add("Places.LandmarksGear.CopyPaste.Action", boost::bind(&LLLandmarksPanel::onClipboardAction, this, _2)); + mCommitCallbackRegistrar.add("Places.LandmarksGear.Custom.Action", boost::bind(&LLLandmarksPanel::onCustomAction, this, _2)); + mCommitCallbackRegistrar.add("Places.LandmarksGear.Folding.Action", boost::bind(&LLLandmarksPanel::onFoldingAction, this, _2)); + mEnableCallbackRegistrar.add("Places.LandmarksGear.Check", boost::bind(&LLLandmarksPanel::isActionChecked, this, _2)); + mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2)); + mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +} + + +void LLLandmarksPanel::updateListCommands() +{ + bool add_folder_enabled = isActionEnabled("category"); + bool trash_enabled = isActionEnabled("delete"); + + // keep Options & Add Landmark buttons always enabled + mListCommands->childSetEnabled(ADD_FOLDER_BUTTON_NAME, add_folder_enabled); + mListCommands->childSetEnabled(TRASH_BUTTON_NAME, trash_enabled); +} + +void LLLandmarksPanel::onActionsButtonClick() +{ + LLFolderViewItem* cur_item = NULL; + if(mCurrentSelectedList) + cur_item = mCurrentSelectedList->getRootFolder()->getCurSelectedItem(); + + if(!cur_item) + return; + + LLFolderViewEventListener* listenerp = cur_item->getListener(); + + LLMenuGL* menu =NULL; + if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) + { + menu = mGearLandmarkMenu; + } + else if (listenerp->getInventoryType() == LLInventoryType::IT_CATEGORY) + { + mGearFolderMenu->getChild<LLMenuItemCallGL>("expand")->setVisible(!cur_item->isOpen()); + mGearFolderMenu->getChild<LLMenuItemCallGL>("collapse")->setVisible(cur_item->isOpen()); + menu = mGearFolderMenu; + } + showActionMenu(menu,OPTIONS_BUTTON_NAME); +} + +void LLLandmarksPanel::onAddButtonHeldDown() +{ + showActionMenu(mMenuAdd,ADD_BUTTON_NAME); +} + +void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_name) +{ + if (menu) + { + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); + LLView* spawning_view = getChild<LLView> (spawning_view_name); + S32 menu_x, menu_y; + //show menu in co-ordinates of panel + spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this); + menu_y += menu->getRect().getHeight(); + LLMenuGL::showPopup(this, menu, menu_x, menu_y); + } +} + +void LLLandmarksPanel::onTrashButtonClick() const +{ + onClipboardAction("delete"); +} + +void LLLandmarksPanel::onAddAction(const LLSD& userdata) const +{ + std::string command_name = userdata.asString(); + if("add_landmark" == command_name) + { + if(LLLandmarkActions::landmarkAlreadyExists()) + { + std::string location; + LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_FULL); + llwarns<<" Landmark already exists at location: "<< location<<llendl; + return; + } + LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark")); + } + else if ("category" == command_name) + { + LLFolderViewItem* item = getCurSelectedItem(); + if (item && mCurrentSelectedList == mLandmarksInventoryPanel) + { + LLFolderViewEventListener* folder_bridge = NULL; + if (item-> getListener()->getInventoryType() + == LLInventoryType::IT_LANDMARK) + { + // for a landmark get parent folder bridge + folder_bridge = item->getParentFolder()->getListener(); + } + else if (item-> getListener()->getInventoryType() + == LLInventoryType::IT_CATEGORY) + { + // for a folder get its own bridge + folder_bridge = item->getListener(); + } + + menu_create_inventory_item(mCurrentSelectedList->getRootFolder(), + dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD( + "category"), gInventory.findCategoryUUIDForType( + LLAssetType::AT_LANDMARK)); + } + } +} + +void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const +{ + if(!mCurrentSelectedList) + return; + std::string command_name = userdata.asString(); + if("copy_slurl" == command_name) + { + LLFolderViewItem* cur_item = getCurSelectedItem(); + if(cur_item) + LLLandmarkActions::copySLURLtoClipboard(cur_item->getListener()->getUUID()); + } + else if ( "paste" == command_name) + { + mCurrentSelectedList->getRootFolder()->paste(); + } + else if ( "cut" == command_name) + { + mCurrentSelectedList->getRootFolder()->cut(); + } + else + { + mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(),command_name); + } +} + +void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) +{ + if(!mCurrentSelectedList) return; + + LLFolderView* root_folder = mCurrentSelectedList->getRootFolder(); + std::string command_name = userdata.asString(); + + if ("expand_all" == command_name) + { + root_folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN); + root_folder->arrangeAll(); + } + else if ("collapse_all" == command_name) + { + root_folder->closeAllFolders(); + } + else if ( "sort_by_date" == command_name) + { + mSortByDate = !mSortByDate; + updateSortOrder(mLandmarksInventoryPanel, mSortByDate); + updateSortOrder(mMyInventoryPanel, mSortByDate); + updateSortOrder(mLibraryInventoryPanel, mSortByDate); + } + else + { + root_folder->doToSelected(&gInventory, userdata); + } +} + +bool LLLandmarksPanel::isActionChecked(const LLSD& userdata) const +{ + const std::string command_name = userdata.asString(); + + if ( "sort_by_date" == command_name) + { + return mSortByDate; + } + + return false; +} + +bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const +{ + std::string command_name = userdata.asString(); + + + LLPlacesFolderView* rootFolderView = mCurrentSelectedList ? + static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()) : NULL; + + if (NULL == rootFolderView) return false; + + // disable some commands for multi-selection. EXT-1757 + if (rootFolderView->getSelectedCount() > 1) + { + if ( "teleport" == command_name + || "more_info" == command_name + || "rename" == command_name + || "show_on_map" == command_name + || "copy_slurl" == command_name + ) + { + return false; + } + + } + + // disable some commands for Favorites accordion. EXT-1758 + if (mCurrentSelectedList == mFavoritesInventoryPanel) + { + if ( "expand_all" == command_name + || "collapse_all" == command_name + || "sort_by_date" == command_name + ) + return false; + } + + + if("category" == command_name) + { + // we can add folder only in Landmarks Accordion + if (mCurrentSelectedList == mLandmarksInventoryPanel) + { + // ... but except Received folder + return !isReceivedFolderSelected(); + } + else return false; + } + else if("paste" == command_name || "rename" == command_name || "cut" == command_name || "delete" == command_name) + { + return canSelectedBeModified(command_name); + } + else if ( "sort_by_date" == command_name) + { + return mSortByDate; + } + else if("create_pick" == command_name) + { + return !LLAgentPicksInfo::getInstance()->isPickLimitReached(); + } + else + { + llwarns << "Unprocessed command has come: " << command_name << llendl; + } + + return true; +} + +void LLLandmarksPanel::onCustomAction(const LLSD& userdata) +{ + LLFolderViewItem* cur_item = getCurSelectedItem(); + if(!cur_item) + return ; + std::string command_name = userdata.asString(); + if("more_info" == command_name) + { + cur_item->getListener()->performAction(mCurrentSelectedList->getRootFolder(),mCurrentSelectedList->getModel(),"about"); + } + else if ("teleport" == command_name) + { + onTeleport(); + } + else if ("show_on_map" == command_name) + { + onShowOnMap(); + } + else if ("create_pick" == command_name) + { + LLLandmark* landmark = getCurSelectedLandmark(); + if(!landmark) return; + + LLViewerRegion* region = gAgent.getRegion(); + if (!region) return; + + LLGlobalVec pos_global; + LLUUID region_id; + landmark->getGlobalPos(pos_global); + landmark->getRegionID(region_id); + LLVector3 region_pos((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS), + (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS), + (F32)pos_global.mdV[VZ]); + + LLSD body; + std::string url = region->getCapability("RemoteParcelRequest"); + if (!url.empty()) + { + body["location"] = ll_sd_from_vector3(region_pos); + 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 create pick for landmark for region" << region_id + << ". Region: " << region->getName() + << " does not support RemoteParcelRequest" << llendl; + } + } +} + +/* +Processes such actions: cut/rename/delete/paste actions + +Rules: + 1. We can't perform any action in Library + 2. For Landmarks we can: + - cut/rename/delete in any other accordions + - paste - only in Favorites, Landmarks accordions + 3. For Folders we can: perform any action in Landmarks accordion, except Received folder + 4. We can not paste folders from Clipboard (processed by LLFolderView::canPaste()) + 5. Check LLFolderView/Inventory Bridges rules + */ +bool LLLandmarksPanel::canSelectedBeModified(const std::string& command_name) const +{ + // validate own rules first + + // nothing can be modified in Library + if (mLibraryInventoryPanel == mCurrentSelectedList) return false; + + bool can_be_modified = false; + + // landmarks can be modified in any other accordion... + if (isLandmarkSelected()) + { + can_be_modified = true; + + // we can modify landmarks anywhere except paste to My Inventory + if ("paste" == command_name) + { + can_be_modified = (mCurrentSelectedList != mMyInventoryPanel); + } + } + else + { + // ...folders only in the Landmarks accordion... + can_be_modified = mLandmarksInventoryPanel == mCurrentSelectedList; + + // ...except "Received" folder + can_be_modified &= !isReceivedFolderSelected(); + } + + // then ask LLFolderView permissions + if (can_be_modified) + { + if ("cut" == command_name) + { + can_be_modified = mCurrentSelectedList->getRootFolder()->canCut(); + } + else if ("rename" == command_name) + { + can_be_modified = getCurSelectedItem()->getListener()->isItemRenameable(); + } + else if ("delete" == command_name) + { + can_be_modified = getCurSelectedItem()->getListener()->isItemRemovable(); + } + else if("paste" == command_name) + { + return mCurrentSelectedList->getRootFolder()->canPaste(); + } + else + { + llwarns << "Unprocessed command has come: " << command_name << llendl; + } + } + + return can_be_modified; +} + +void LLLandmarksPanel::onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params) +{ + pick_panel->setVisible(FALSE); + owner->removeChild(pick_panel); + //we need remove observer to avoid processParcelInfo in the future. + LLRemoteParcelInfoProcessor::getInstance()->removeObserver(params["parcel_id"].asUUID(), this); + + delete pick_panel; + pick_panel = NULL; +} + +bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept) +{ + *accept = ACCEPT_NO; + + switch (cargo_type) + { + + case DAD_LANDMARK: + case DAD_CATEGORY: + { + bool is_enabled = isActionEnabled("delete"); + + if (is_enabled) *accept = ACCEPT_YES_MULTI; + + if (is_enabled && drop) + { + onClipboardAction("delete"); + } + } + break; + default: + break; + } + + return true; +} + +// static +void LLLandmarksPanel::doIdle(void* landmarks_panel) +{ + LLLandmarksPanel* panel = (LLLandmarksPanel* ) landmarks_panel; + + if (panel->mDirtyFilter) + { + panel->updateFilteredAccordions(); + } + +} + +void LLLandmarksPanel::updateFilteredAccordions() +{ + LLInventoryPanel* inventory_list = NULL; + LLAccordionCtrlTab* accordion_tab = NULL; + for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter) + { + accordion_tab = *iter; + inventory_list = dynamic_cast<LLInventorySubTreePanel*> (accordion_tab->getAccordionView()); + if (NULL == inventory_list) continue; + LLFolderView* fv = inventory_list->getRootFolder(); + + bool has_visible_children = fv->hasVisibleChildren(); + + accordion_tab->setVisible(has_visible_children); + } + + // we have to arrange accordion tabs for cases when filter string is less restrictive but + // all items are still filtered. + static LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion"); + accordion->arrange(); + + // now filter state is applied to accordion tabs + mDirtyFilter = false; +} + + +////////////////////////////////////////////////////////////////////////// +// HELPER FUNCTIONS +////////////////////////////////////////////////////////////////////////// +static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string) +{ + if (string == "") + { + inventory_list->setFilterSubString(LLStringUtil::null); + + // re-open folders that were initially open + inventory_list->restoreFolderState(); + } + + gInventory.startBackgroundFetch(); + + if (inventory_list->getFilterSubString().empty() && string.empty()) + { + // current filter and new filter empty, do nothing + return; + } + + // save current folder open state if no filter currently applied + if (inventory_list->getRootFolder()->getFilterSubString().empty()) + { + inventory_list->saveFolderState(); + } + + // set new filter string + inventory_list->setFilterSubString(string); +} +// EOF diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp index 6a3617f008..a198499b47 100644 --- a/indra/newview/llpanelmediasettingsgeneral.cpp +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -134,6 +134,11 @@ void LLPanelMediaSettingsGeneral::draw() LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin();
if( media_plugin )
{
+ // turn off volume (if we can) for preview. Note: this really only
+ // works for QuickTime movies right now - no way to control the
+ // volume of a flash app embedded in a page for example
+ media_plugin->setVolume( 0 );
+
// some controls are only appropriate for time or browser type plugins
// so we selectively enable/disable them - need to do it in draw
// because the information from plugins arrives assynchronously
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index aa6909560d..6181531f82 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -73,10 +73,10 @@ LLPanelPicks::LLPanelPicks() mPopupMenu(NULL), mProfilePanel(NULL), mPickPanel(NULL), - mPicksList(NULL) - , mPanelPickInfo(NULL) - , mPanelPickEdit(NULL) - , mOverflowMenu(NULL) + mPicksList(NULL), + mPanelPickInfo(NULL), + mPanelPickEdit(NULL), + mOverflowMenu(NULL) { } diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index ca7ebb1ad8..e4b32c4820 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -127,7 +127,7 @@ BOOL LLPanelPrimMediaControls::postBuild() scroll_left_ctrl->setMouseUpCallback(onScrollStop, this); LLButton* scroll_right_ctrl = getChild<LLButton>("scrollright"); scroll_right_ctrl->setClickedCallback(onScrollRight, this); - scroll_right_ctrl->setHeldDownCallback(onScrollLeftHeld, this); + scroll_right_ctrl->setHeldDownCallback(onScrollRightHeld, this); scroll_right_ctrl->setMouseUpCallback(onScrollStop, this); LLButton* scroll_down_ctrl = getChild<LLButton>("scrolldown"); scroll_down_ctrl->setClickedCallback(onScrollDown, this); @@ -258,7 +258,8 @@ void LLPanelPrimMediaControls::updateShape() LLUICtrl* zoom_ctrl = getChild<LLUICtrl>("zoom_frame"); LLPanel* media_loading_panel = getChild<LLPanel>("media_progress_indicator"); LLUICtrl* media_address_ctrl = getChild<LLUICtrl>("media_address"); - LLUICtrl* media_play_slider_ctrl = getChild<LLUICtrl>("media_play_position"); + LLUICtrl* media_play_slider_panel = getChild<LLUICtrl>("media_play_position"); + LLUICtrl* media_play_slider_ctrl = getChild<LLUICtrl>("media_play_slider"); LLUICtrl* volume_ctrl = getChild<LLUICtrl>("media_volume"); LLButton* volume_btn = getChild<LLButton>("media_volume_button"); LLUICtrl* volume_up_ctrl = getChild<LLUICtrl>("volume_up"); @@ -282,7 +283,7 @@ void LLPanelPrimMediaControls::updateShape() close_ctrl->setVisible(has_focus); open_ctrl->setVisible(true); media_address_ctrl->setVisible(has_focus && !mini_controls); - media_play_slider_ctrl->setVisible(has_focus && !mini_controls); + media_play_slider_panel->setVisible(has_focus && !mini_controls); volume_ctrl->setVisible(false); volume_up_ctrl->setVisible(false); volume_down_ctrl->setVisible(false); @@ -291,7 +292,7 @@ void LLPanelPrimMediaControls::updateShape() // Disable zoom if HUD zoom_ctrl->setEnabled(!objectp->isHUDAttachment()); secure_lock_icon->setVisible(false); - mCurrentURL = media_impl->getMediaURL(); + mCurrentURL = media_impl->getCurrentMediaURL(); back_ctrl->setEnabled((media_impl != NULL) && media_impl->canNavigateBack() && can_navigate); fwd_ctrl->setEnabled((media_impl != NULL) && media_impl->canNavigateForward() && can_navigate); @@ -309,8 +310,8 @@ void LLPanelPrimMediaControls::updateShape() fwd_ctrl->setEnabled(has_focus); media_address_ctrl->setVisible(false); media_address_ctrl->setEnabled(false); - media_play_slider_ctrl->setVisible(!mini_controls); - media_play_slider_ctrl->setEnabled(!mini_controls); + media_play_slider_panel->setVisible(!mini_controls); + media_play_slider_panel->setEnabled(!mini_controls); volume_ctrl->setVisible(has_focus); volume_up_ctrl->setVisible(has_focus); @@ -406,8 +407,8 @@ void LLPanelPrimMediaControls::updateShape() media_stop_ctrl->setVisible(FALSE); media_address_ctrl->setVisible(has_focus && !mini_controls); media_address_ctrl->setEnabled(has_focus && !mini_controls); - media_play_slider_ctrl->setVisible(FALSE); - media_play_slider_ctrl->setEnabled(FALSE); + media_play_slider_panel->setVisible(FALSE); + media_play_slider_panel->setEnabled(FALSE); volume_ctrl->setVisible(FALSE); volume_up_ctrl->setVisible(FALSE); @@ -472,7 +473,7 @@ void LLPanelPrimMediaControls::updateShape() } } - if(media_plugin) + if(media_impl) { // // Handle Scrolling @@ -480,16 +481,18 @@ void LLPanelPrimMediaControls::updateShape() switch (mScrollState) { case SCROLL_UP: - media_plugin->scrollEvent(0, -1, MASK_NONE); + media_impl->scrollWheel(0, -1, MASK_NONE); break; case SCROLL_DOWN: - media_plugin->scrollEvent(0, 1, MASK_NONE); + media_impl->scrollWheel(0, 1, MASK_NONE); break; case SCROLL_LEFT: - media_impl->handleKeyHere(KEY_LEFT, MASK_NONE); + media_impl->scrollWheel(1, 0, MASK_NONE); +// media_impl->handleKeyHere(KEY_LEFT, MASK_NONE); break; case SCROLL_RIGHT: - media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE); + media_impl->scrollWheel(-1, 0, MASK_NONE); +// media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE); break; case SCROLL_NONE: default: @@ -592,9 +595,9 @@ void LLPanelPrimMediaControls::updateShape() mLastCursorPos = cursor_pos_window; } - if(isMouseOver()) + if(isMouseOver() || hasFocus()) { - // Never fade the controls if the mouse is over them. + // Never fade the controls if the mouse is over them or they have keyboard focus. mFadeTimer.stop(); } else if(!mClearFaceOnFade && (mInactivityTimer.getElapsedTimeF32() < mInactiveTimeout)) @@ -627,9 +630,13 @@ void LLPanelPrimMediaControls::draw() if(mFadeTimer.getElapsedTimeF32() >= mControlFadeTime) { - setVisible(FALSE); if(mClearFaceOnFade) { + // Hiding this object makes scroll events go missing after it fades out + // (see DEV-41755 for a full description of the train wreck). + // Only hide the controls when we're untargeting. + setVisible(FALSE); + mClearFaceOnFade = false; mTargetImplID = LLUUID::null; mTargetObjectID = LLUUID::null; @@ -758,20 +765,10 @@ void LLPanelPrimMediaControls::onClickHome() void LLPanelPrimMediaControls::onClickOpen() { - LLViewerMediaImpl* impl =getTargetMediaImpl(); + LLViewerMediaImpl* impl = getTargetMediaImpl(); if(impl) { - if(impl->getMediaPlugin()) - { - if(impl->getMediaPlugin()->getLocation().empty()) - { - LLWeb::loadURL(impl->getMediaURL()); - } - else - { - LLWeb::loadURL( impl->getMediaPlugin()->getLocation()); - } - } + LLWeb::loadURL(impl->getCurrentMediaURL()); } } @@ -895,11 +892,11 @@ void LLPanelPrimMediaControls::onScrollUp(void* user_data) LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data); this_panel->focusOnTarget(); - LLPluginClassMedia* plugin = this_panel->getTargetMediaPlugin(); + LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl(); - if(plugin) + if(impl) { - plugin->scrollEvent(0, -1, MASK_NONE); + impl->scrollWheel(0, -1, MASK_NONE); } } void LLPanelPrimMediaControls::onScrollUpHeld(void* user_data) @@ -916,7 +913,8 @@ void LLPanelPrimMediaControls::onScrollRight(void* user_data) if(impl) { - impl->handleKeyHere(KEY_RIGHT, MASK_NONE); + impl->scrollWheel(-1, 0, MASK_NONE); +// impl->handleKeyHere(KEY_RIGHT, MASK_NONE); } } void LLPanelPrimMediaControls::onScrollRightHeld(void* user_data) @@ -934,7 +932,8 @@ void LLPanelPrimMediaControls::onScrollLeft(void* user_data) if(impl) { - impl->handleKeyHere(KEY_LEFT, MASK_NONE); + impl->scrollWheel(1, 0, MASK_NONE); +// impl->handleKeyHere(KEY_LEFT, MASK_NONE); } } void LLPanelPrimMediaControls::onScrollLeftHeld(void* user_data) @@ -948,11 +947,11 @@ void LLPanelPrimMediaControls::onScrollDown(void* user_data) LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data); this_panel->focusOnTarget(); - LLPluginClassMedia* plugin = this_panel->getTargetMediaPlugin(); + LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl(); - if(plugin) + if(impl) { - plugin->scrollEvent(0, 1, MASK_NONE); + impl->scrollWheel(0, 1, MASK_NONE); } } void LLPanelPrimMediaControls::onScrollDownHeld(void* user_data) @@ -1000,6 +999,7 @@ void LLPanelPrimMediaControls::onInputURL(LLFocusableElement* caller, void *user void LLPanelPrimMediaControls::setCurrentURL() { +#ifdef USE_COMBO_BOX_FOR_MEDIA_URL LLComboBox* media_address_combo = getChild<LLComboBox>("media_address_combo"); // redirects will navigate momentarily to about:blank, don't add to history if (media_address_combo && mCurrentURL != "about:blank") @@ -1008,6 +1008,13 @@ void LLPanelPrimMediaControls::setCurrentURL() media_address_combo->add(mCurrentURL, ADD_SORTED); media_address_combo->selectByValue(mCurrentURL); } +#else // USE_COMBO_BOX_FOR_MEDIA_URL + LLLineEditor* media_address_url = getChild<LLLineEditor>("media_address_url"); + if (media_address_url && mCurrentURL != "about:blank") + { + media_address_url->setValue(mCurrentURL); + } +#endif // USE_COMBO_BOX_FOR_MEDIA_URL } void LLPanelPrimMediaControls::onCommitSlider() diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 73dcd1dd92..e4dbcbd219 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -44,7 +44,6 @@ #include "lltrans.h" #include "lldockablefloater.h" -#include "llimpanel.h" #include "llsyswellwindow.h" #include "llimfloater.h" diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 43b039f94e..9aa74e8b9f 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1149,7 +1149,8 @@ bool idle_startup() } //setup map of datetime strings to codes and slt & local time offset from utc - LLStringOps::setupDatetimeInfo (gPacificDaylightTime); + // *TODO: Does this need to be here? + LLStringOps::setupDatetimeInfo (false); transition_back_to_login_panel(emsg.str()); show_connect_box = true; } @@ -3037,14 +3038,15 @@ bool process_login_success_response() gAgent.setGenderChosen(TRUE); } + bool pacific_daylight_time = false; flag = login_flags["daylight_savings"].asString(); if(flag == "Y") { - gPacificDaylightTime = (flag == "Y") ? TRUE : FALSE; + pacific_daylight_time = (flag == "Y"); } //setup map of datetime strings to codes and slt & local time offset from utc - LLStringOps::setupDatetimeInfo (gPacificDaylightTime); + LLStringOps::setupDatetimeInfo(pacific_daylight_time); } LLSD initial_outfit = response["initial-outfit"][0]; diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 93a931dc78..419603e14e 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -427,7 +427,6 @@ void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId) { delIMRow(sessionId); reshapeWindow(); - LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications(); } void LLSysWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) diff --git a/indra/newview/lltexlayerparams.cpp b/indra/newview/lltexlayerparams.cpp index e1643af71d..74e0fa077e 100644 --- a/indra/newview/lltexlayerparams.cpp +++ b/indra/newview/lltexlayerparams.cpp @@ -42,8 +42,7 @@ //----------------------------------------------------------------------------- LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) : mTexLayer(layer), - mAvatar(NULL), - mIsWearableParam(TRUE) + mAvatar(NULL) { if (mTexLayer != NULL) { @@ -56,8 +55,7 @@ LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) : } LLTexLayerParam::LLTexLayerParam(LLVOAvatar *avatar) : - mTexLayer(NULL), - mIsWearableParam(FALSE) + mTexLayer(NULL) { mAvatar = avatar; } @@ -177,7 +175,7 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user) { mCurWeight = new_weight; - if ((mAvatar->getSex() & getSex()) && !mIsWearableParam) // only trigger a baked texture update if we're changing a wearable's visual param. + if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. { if (gAgent.cameraCustomizeAvatar()) { @@ -192,6 +190,13 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user) void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL set_by_user) { + // do not animate dummy parameters + if (mIsDummy) + { + setWeight(target_value, set_by_user); + return; + } + mTargetWeight = target_value; setWeight(target_value, set_by_user); mIsAnimating = TRUE; @@ -468,7 +473,7 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL set_by_user) return; } - if ((mAvatar->getSex() & getSex()) && !mIsWearableParam) // only trigger a baked texture update if we're changing a wearable's visual param. + if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. { onGlobalColorChanged(set_by_user); if (mTexLayer) diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h index dcb108bbf6..98365864f9 100644 --- a/indra/newview/lltexlayerparams.h +++ b/indra/newview/lltexlayerparams.h @@ -49,7 +49,6 @@ public: protected: LLTexLayerInterface* mTexLayer; LLVOAvatar* mAvatar; - BOOL mIsWearableParam; }; //----------------------------------------------------------------------------- diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 9f0e205712..50ebc205a9 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -460,7 +460,7 @@ BOOL LLFloaterTexturePicker::postBuild() // virtual void LLFloaterTexturePicker::draw() { - static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0); + S32 floater_header_size = getHeaderHeight(); if (mOwner) { // draw cone of context pointing back to texture swatch diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 24824a095c..903df21e78 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -49,13 +49,15 @@ LLToast::Params::Params() enable_hide_btn("enable_hide_btn", true), force_show("force_show", false), force_store("force_store", false), + fading_time_secs("fading_time_secs", gSavedSettings.getS32("ToastFadingTime")), lifetime_secs("lifetime_secs", gSavedSettings.getS32("NotificationToastLifeTime")) {}; LLToast::LLToast(const LLToast::Params& p) : LLModalDialog(LLSD(), p.is_modal), mPanel(p.panel), - mToastLifetime(p.lifetime_secs), + mToastLifetime(p.lifetime_secs), + mToastFadingTime(p.fading_time_secs), mNotificationID(p.notif_id), mSessionID(p.session_id), mCanFade(p.can_fade), @@ -127,7 +129,7 @@ bool LLToast::lifetimeHasExpired() if (mTimer.getStarted()) { F32 elapsed_time = mTimer.getElapsedTimeF32(); - if ((mToastLifetime - elapsed_time) <= gSavedSettings.getS32("ToastOpaqueTime")) + if ((mToastLifetime - elapsed_time) <= mToastFadingTime) { setBackgroundOpaque(FALSE); } diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 0698c94880..b670f47045 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -63,7 +63,8 @@ public: Optional<LLUUID> notif_id, //notification ID session_id; //im session ID Optional<LLNotificationPtr> notification; - Optional<F32> lifetime_secs; + Optional<F32> lifetime_secs, + fading_time_secs; // Number of seconds while a toast is fading Optional<toast_callback_t> on_delete_toast, on_mouse_enter; Optional<bool> can_fade, @@ -157,6 +158,7 @@ private: // timer counts a lifetime of a toast LLTimer mTimer; F32 mToastLifetime; // in seconds + F32 mToastFadingTime; // in seconds LLPanel* mPanel; LLButton* mHideBtn; diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index c2cd63900b..c02fd7a5ef 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -32,7 +32,6 @@ #include "llviewerprecompiledheaders.h" #include "lltoastimpanel.h" -#include "llimpanel.h" const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 6; diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 7c17699bf9..304f1dffaf 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -732,7 +732,47 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask) { tooltip_msg.append( nodep->mName ); } - + + bool is_time_based_media = false; + bool is_web_based_media = false; + bool is_media_playing = false; + + // Does this face have media? + const LLTextureEntry* tep = hover_object->getTE(mHoverPick.mObjectFace); + + if(tep) + { + const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; + if (mep) + { + viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL; + LLPluginClassMedia* media_plugin = NULL; + + if (media_impl.notNull() && (media_impl->hasMedia())) + { + LLStringUtil::format_map_t args; + + media_plugin = media_impl->getMediaPlugin(); + if(media_plugin) + { if(media_plugin->pluginSupportsMediaTime()) + { + is_time_based_media = true; + is_web_based_media = false; + args["[CurrentURL]"] = media_impl->getMediaURL(); + is_media_playing = media_impl->isMediaPlaying(); + } + else + { + is_time_based_media = false; + is_web_based_media = true; + args["[CurrentURL]"] = media_plugin->getLocation(); + } + //tooltip_msg.append(LLTrans::getString("CurrentURL", args)); + } + } + } + } + bool needs_tip = needs_tooltip(nodep); if (show_all_object_tips || needs_tip) @@ -741,8 +781,13 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask) mPick = mHoverPick; LLToolTipMgr::instance().show(LLToolTip::Params() .message(tooltip_msg) - .image(LLUI::getUIImage("Info")) - .click_callback(boost::bind(showObjectInspector, hover_object->getID())) + .image(LLUI::getUIImage("Info_Off")) + .click_callback(boost::bind(showObjectInspector, hover_object->getID(), mHoverPick.mObjectFace)) + .time_based_media(is_time_based_media) + .web_based_media(is_web_based_media) + .media_playing(is_media_playing) + .click_playmedia_callback(boost::bind(playCurrentMedia, mHoverPick)) + .click_homepage_callback(boost::bind(VisitHomePage, mHoverPick)) .visible_time_near(6.f) .visible_time_far(3.f) .wrap(false)); @@ -925,6 +970,20 @@ static void show_inspector(const char* inspector, const char* param, const LLUUI LLFloaterReg::showInstance(inspector, params); } + +static void show_inspector(const char* inspector, LLSD& params) +{ + if (LLToolTipMgr::instance().toolTipVisible()) + { + LLRect rect = LLToolTipMgr::instance().getToolTipRect(); + params["pos"]["x"] = rect.mLeft; + params["pos"]["y"] = rect.mTop; + } + + LLFloaterReg::showInstance(inspector, params); +} + + // static void LLToolPie::showAvatarInspector(const LLUUID& avatar_id) { @@ -937,6 +996,114 @@ void LLToolPie::showObjectInspector(const LLUUID& object_id) show_inspector("inspect_object", "object_id", object_id); } + +// static +void LLToolPie::showObjectInspector(const LLUUID& object_id, const S32& object_face) +{ + LLSD params; + params["object_id"] = object_id; + params["object_face"] = object_face; + show_inspector("inspect_object", params); +} + +// static +void LLToolPie::playCurrentMedia(const LLPickInfo& info) +{ + //FIXME: how do we handle object in different parcel than us? + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!parcel) return; + + LLPointer<LLViewerObject> objectp = info.getObject(); + + // Early out cases. Must clear media hover. + // did not hit an object or did not hit a valid face + if ( objectp.isNull() || + info.mObjectFace < 0 || + info.mObjectFace >= objectp->getNumTEs() ) + { + return; + } + + // Does this face have media? + const LLTextureEntry* tep = objectp->getTE(info.mObjectFace); + if (!tep) + return; + + const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; + if(!mep) + return; + + LLPluginClassMedia* media_plugin = NULL; + +// if (gSavedSettings.getBOOL("MediaOnAPrimUI")) +// { + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); + + if(media_impl.notNull() && media_impl->hasMedia()) + { + media_plugin = media_impl->getMediaPlugin(); + + if (media_plugin && media_plugin->pluginSupportsMediaTime()) + { + if(media_impl->isMediaPlaying()) + { + media_impl->pause(); + } + else //if(media_impl->isMediaPaused()) + { + media_impl->play(); + } + + } + + } +// } + +} + +// static +void LLToolPie::VisitHomePage(const LLPickInfo& info) +{ + //FIXME: how do we handle object in different parcel than us? + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!parcel) return; + + LLPointer<LLViewerObject> objectp = info.getObject(); + + // Early out cases. Must clear media hover. + // did not hit an object or did not hit a valid face + if ( objectp.isNull() || + info.mObjectFace < 0 || + info.mObjectFace >= objectp->getNumTEs() ) + { + return; + } + + // Does this face have media? + const LLTextureEntry* tep = objectp->getTE(info.mObjectFace); + if (!tep) + return; + + const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; + if(!mep) + return; + + LLPluginClassMedia* media_plugin = NULL; + + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); + + if(media_impl.notNull() && media_impl->hasMedia()) + { + media_plugin = media_impl->getMediaPlugin(); + + if (media_plugin && !(media_plugin->pluginSupportsMediaTime())) + { + media_impl->navigateHome(); + } + } +} + + void LLToolPie::handleDeselect() { if( hasMouseCapture() ) @@ -1035,12 +1202,17 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick) // Does this face have media? const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); + if(!tep) + return false; + LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL; + + if(!mep) + return false; + viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL; - if (tep - && mep - && gSavedSettings.getBOOL("MediaOnAPrimUI") + if (gSavedSettings.getBOOL("MediaOnAPrimUI") && media_impl.notNull()) { if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) ) @@ -1085,6 +1257,9 @@ bool LLToolPie::handleMediaHover(const LLPickInfo& pick) // Does this face have media? const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); + if(!tep) + return false; + const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; if (mep && gSavedSettings.getBOOL("MediaOnAPrimUI")) diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index 5faedbec5a..3660c68552 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -78,6 +78,10 @@ public: static void showAvatarInspector(const LLUUID& avatar_id); static void showObjectInspector(const LLUUID& object_id); + static void showObjectInspector(const LLUUID& object_id, const S32& object_face); + static void playCurrentMedia(const LLPickInfo& info); + static void VisitHomePage(const LLPickInfo& info); + private: BOOL outsideSlop (S32 x, S32 y, S32 start_x, S32 start_y); BOOL pickLeftMouseDownCallback(); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index b71291f834..35226a1632 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -511,13 +511,34 @@ bool toggle_show_snapshot_button(const LLSD& newvalue) bool toggle_show_navigation_panel(const LLSD& newvalue) { - LLNavigationBar::getInstance()->showNavigationPanel(newvalue.asBoolean()); + LLRect floater_view_rect = gFloaterView->getRect(); + LLRect notify_view_rect = gNotifyBoxView->getRect(); + LLNavigationBar* navbar = LLNavigationBar::getInstance(); + + //if newvalue contains 0 => navbar should turn invisible, so floater_view_rect should get higher, + //and to do this pm=1, else if navbar becomes visible pm=-1 so floater_view_rect gets lower. + int pm=newvalue.asBoolean()?-1:1; + floater_view_rect.mTop += pm*(navbar->getDefNavBarHeight()-navbar->getDefFavBarHeight()); + notify_view_rect.mTop += pm*(navbar->getDefNavBarHeight()-navbar->getDefFavBarHeight()); + gFloaterView->setRect(floater_view_rect); + floater_view_rect = gFloaterView->getRect(); + navbar->showNavigationPanel(newvalue.asBoolean()); return true; } bool toggle_show_favorites_panel(const LLSD& newvalue) { - LLNavigationBar::getInstance()->showFavoritesPanel(newvalue.asBoolean()); + LLRect floater_view_rect = gFloaterView->getRect(); + LLRect notify_view_rect = gNotifyBoxView->getRect(); + LLNavigationBar* navbar = LLNavigationBar::getInstance(); + + //if newvalue contains 0 => favbar should turn invisible, so floater_view_rect should get higher, + //and to do this pm=1, else if favbar becomes visible pm=-1 so floater_view_rect gets lower. + int pm=newvalue.asBoolean()?-1:1; + floater_view_rect.mTop += pm*navbar->getDefFavBarHeight(); + notify_view_rect.mTop += pm*navbar->getDefFavBarHeight(); + gFloaterView->setRect(floater_view_rect); + navbar->showFavoritesPanel(newvalue.asBoolean()); return true; } diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h index b1f14eca7b..9b4e80cae0 100644 --- a/indra/newview/llviewercontrol.h +++ b/indra/newview/llviewercontrol.h @@ -43,6 +43,9 @@ extern BOOL gHackGodmode; #endif +bool toggle_show_navigation_panel(const LLSD& newvalue); +bool toggle_show_favorites_panel(const LLSD& newvalue); + // These functions found in llcontroldef.cpp *TODO: clean this up! //setting variables are declared in this function void settings_setup_listeners(); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index dace3f875f..9ca2d3f61d 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -80,6 +80,7 @@ #include "llfloatermap.h" #include "llfloatermemleak.h" #include "llfloaternamedesc.h" +#include "llfloaternearbymedia.h" #include "llfloaternotificationsconsole.h" #include "llfloateropenobject.h" #include "llfloaterpay.h" @@ -187,6 +188,8 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGetBlockedObjectName>); LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>); LLFloaterReg::add("syswell_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLSysWellWindow>); + + LLFloaterReg::add("nearby_media", "floater_nearby_media.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNearbyMedia>); LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 8bd74dcb04..e89f17cf72 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -168,8 +168,7 @@ public: viewer_media_t mMediaImpl; bool mInitialized; }; -typedef std::vector<LLViewerMediaImpl*> impl_list; -static impl_list sViewerMediaImplList; +static LLViewerMedia::impl_list sViewerMediaImplList; static LLTimer sMediaCreateTimer; static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f; static F32 sGlobalVolume = 1.0f; @@ -183,8 +182,8 @@ static void add_media_impl(LLViewerMediaImpl* media) ////////////////////////////////////////////////////////////////////////////////////////// static void remove_media_impl(LLViewerMediaImpl* media) { - impl_list::iterator iter = sViewerMediaImplList.begin(); - impl_list::iterator end = sViewerMediaImplList.end(); + LLViewerMedia::impl_list::iterator iter = sViewerMediaImplList.begin(); + LLViewerMedia::impl_list::iterator end = sViewerMediaImplList.end(); for(; iter != end; iter++) { @@ -203,6 +202,7 @@ class LLViewerMediaMuteListObserver : public LLMuteListObserver static LLViewerMediaMuteListObserver sViewerMediaMuteListObserver; static bool sViewerMediaMuteListObserverInitialized = false; +static bool sInWorldMediaDisabled = false; ////////////////////////////////////////////////////////////////////////////////////////// @@ -428,15 +428,34 @@ void LLViewerMedia::muteListChanged() } } +////////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::setInWorldMediaDisabled(bool disabled) +{ + sInWorldMediaDisabled = disabled; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static +bool LLViewerMedia::getInWorldMediaDisabled() +{ + return sInWorldMediaDisabled; +} + +LLViewerMedia::impl_list &LLViewerMedia::getPriorityList() +{ + return sViewerMediaImplList; +} + // This is the predicate function used to sort sViewerMediaImplList by priority. -static inline bool compare_impl_interest(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2) +bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2) { - if(i1->mIsMuted || i1->mMediaSourceFailed) + if(i1->isForcedUnloaded()) { // Muted or failed items always go to the end of the list, period. return false; } - else if(i2->mIsMuted || i2->mMediaSourceFailed) + else if(i2->isForcedUnloaded()) { // Muted or failed items always go to the end of the list, period. return true; @@ -483,7 +502,7 @@ void LLViewerMedia::updateMedia() } // Sort the static instance list using our interest criteria - std::stable_sort(sViewerMediaImplList.begin(), sViewerMediaImplList.end(), compare_impl_interest); + std::stable_sort(sViewerMediaImplList.begin(), sViewerMediaImplList.end(), priorityComparitor); // Go through the list again and adjust according to priority. iter = sViewerMediaImplList.begin(); @@ -493,6 +512,7 @@ void LLViewerMedia::updateMedia() int impl_count_total = 0; int impl_count_interest_low = 0; int impl_count_interest_normal = 0; + int i = 0; #if 0 LL_DEBUGS("PluginPriority") << "Sorted impls:" << llendl; @@ -515,7 +535,7 @@ void LLViewerMedia::updateMedia() LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL; - if(pimpl->mIsMuted || pimpl->mMediaSourceFailed || (impl_count_total > (int)max_instances)) + if(pimpl->isForcedUnloaded() || (impl_count_total > (int)max_instances)) { // Never load muted or failed impls. // Hard limit on the number of instances that will be loaded at one time @@ -583,6 +603,17 @@ void LLViewerMedia::updateMedia() } pimpl->setPriority(new_priority); + + if(pimpl->getUsedInUI()) + { + // Any impls used in the UI should not be in the proximity list. + pimpl->mProximity = -1; + } + else + { + // Other impls just get the same ordering as the priority list (for now). + pimpl->mProximity = i; + } #if 0 LL_DEBUGS("PluginPriority") << " " << pimpl @@ -595,6 +626,8 @@ void LLViewerMedia::updateMedia() #endif total_cpu += pimpl->getCPUUsage(); + + i++; } LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << llendl; @@ -641,6 +674,8 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mNeedsMuteCheck(false), mPreviousMediaState(MEDIA_NONE), mPreviousMediaTime(0.0f), + mIsDisabled(false), + mProximity(-1), mIsUpdated(false) { @@ -1023,6 +1058,16 @@ bool LLViewerMediaImpl::hasFocus() const return mHasFocus; } +std::string LLViewerMediaImpl::getCurrentMediaURL() +{ + if(!mCurrentMediaURL.empty()) + { + return mCurrentMediaURL; + } + + return mMediaURL; +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseDown(S32 x, S32 y, MASK mask, S32 button) { @@ -1109,6 +1154,18 @@ void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button) } ////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, MASK mask) +{ + scaleMouse(&x, &y); + mLastMouseX = x; + mLastMouseY = y; + if (mMediaSource) + { + mMediaSource->scrollEvent(x, y, mask); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::onMouseCaptureLost() { if (mMediaSource) @@ -1181,7 +1238,7 @@ void LLViewerMediaImpl::navigateForward() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::navigateReload() { - navigateTo(mMediaURL, "", true, false); + navigateTo(getCurrentMediaURL(), "", true, false); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1203,6 +1260,9 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi mMediaURL = url; mMimeType = mime_type; + // Clear the current media URL, since it will no longer be correct. + mCurrentMediaURL.clear(); + // if mime type discovery was requested, we'll need to do it when the media loads mNavigateRediscoverType = rediscover_type; @@ -1537,7 +1597,7 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() ////////////////////////////////////////////////////////////////////////////////////////// -LLUUID LLViewerMediaImpl::getMediaTextureID() +LLUUID LLViewerMediaImpl::getMediaTextureID() const { return mTextureId; } @@ -1625,6 +1685,27 @@ void LLViewerMediaImpl::resetPreviousMediaState() } ////////////////////////////////////////////////////////////////////////////////////////// +// +bool LLViewerMediaImpl::isForcedUnloaded() const +{ + if(mIsMuted || mMediaSourceFailed || mIsDisabled) + { + return true; + } + + if(sInWorldMediaDisabled) + { + // When inworld media is disabled, all instances that aren't marked as "used in UI" will not be loaded. + if(!mUsedInUI) + { + return true; + } + } + + return false; +} + +////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event) { switch(event) @@ -1702,10 +1783,12 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla if(getNavState() == MEDIANAVSTATE_BEGUN) { + mCurrentMediaURL = plugin->getNavigateURI(); setNavState(MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED); } else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN) { + mCurrentMediaURL = plugin->getNavigateURI(); setNavState(MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED); } else @@ -1721,10 +1804,12 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla if(getNavState() == MEDIANAVSTATE_BEGUN) { + mCurrentMediaURL = plugin->getLocation(); setNavState(MEDIANAVSTATE_FIRST_LOCATION_CHANGED); } else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN) { + mCurrentMediaURL = plugin->getLocation(); setNavState(MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED); } else @@ -1988,6 +2073,19 @@ const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const return &mObjectList ; } +LLVOVolume *LLViewerMediaImpl::getSomeObject() +{ + LLVOVolume *result = NULL; + + std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ; + if(iter != mObjectList.end()) + { + result = *iter; + } + + return result; +} + ////////////////////////////////////////////////////////////////////////////////////////// //static void LLViewerMedia::toggleMusicPlay(void*) diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 4f0d39dd80..dac0482078 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -66,10 +66,15 @@ private: observerListType mObservers; }; +class LLViewerMediaImpl; + class LLViewerMedia { LOG_CLASS(LLViewerMedia); public: + + typedef std::vector<LLViewerMediaImpl*> impl_list; + // Special case early init for just web browser component // so we can show login screen. See .cpp file for details. JC @@ -97,6 +102,14 @@ class LLViewerMedia static void mediaStop(void*); static F32 getVolume(); static void muteListChanged(); + static void setInWorldMediaDisabled(bool disabled); + static bool getInWorldMediaDisabled(); + + // Returns the priority-sorted list of all media impls. + static impl_list &getPriorityList(); + + // This is the comparitor used to sort the list. + static bool priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2); }; // Implementation functions not exported into header file @@ -145,6 +158,7 @@ public: void mouseUp(const LLVector2& texture_coords, MASK mask, S32 button = 0); void mouseMove(const LLVector2& texture_coords, MASK mask); void mouseDoubleClick(S32 x,S32 y, MASK mask, S32 button = 0); + void scrollWheel(S32 x, S32 y, MASK mask); void mouseCapture(); void navigateBack(); @@ -158,7 +172,8 @@ public: bool handleUnicodeCharHere(llwchar uni_char); bool canNavigateForward(); bool canNavigateBack(); - std::string getMediaURL() { return mMediaURL; } + std::string getMediaURL() const { return mMediaURL; } + std::string getCurrentMediaURL(); std::string getHomeURL() { return mHomeURL; } void setHomeURL(const std::string& home_url) { mHomeURL = home_url; }; std::string getMimeType() { return mMimeType; } @@ -166,7 +181,7 @@ public: void update(); void updateImagesMediaStreams(); - LLUUID getMediaTextureID(); + LLUUID getMediaTextureID() const; void suspendUpdates(bool suspend) { mSuspendUpdates = suspend; }; void setVisible(bool visible); @@ -177,6 +192,12 @@ public: bool hasMedia(); bool isMediaFailed() { return mMediaSourceFailed; }; void resetPreviousMediaState(); + + void setDisabled(bool disabled) { mIsDisabled = disabled; }; + bool isMediaDisabled() { return mIsDisabled; }; + + // returns true if this instance should not be loaded (disabled, muted object, crashed, etc.) + bool isForcedUnloaded() const; ECursorType getLastSetCursor() { return mLastSetCursor; }; @@ -229,6 +250,7 @@ public: void addObject(LLVOVolume* obj) ; void removeObject(LLVOVolume* obj) ; const std::list< LLVOVolume* >* getObjectList() const ; + LLVOVolume *getSomeObject(); void setUpdated(BOOL updated) ; BOOL isUpdated() ; @@ -236,6 +258,7 @@ public: void calculateInterest(); F64 getInterest() const { return mInterest; }; F64 getApproximateTextureInterest(); + S32 getProximity() { return mProximity; }; // Mark this object as being used in a UI panel instead of on a prim // This will be used as part of the interest sorting algorithm. @@ -272,9 +295,10 @@ public: LLPluginClassMedia* mMediaSource; LLUUID mTextureId; bool mMovieImageHasMips; - std::string mMediaURL; + std::string mMediaURL; // The last media url set with NavigateTo std::string mHomeURL; std::string mMimeType; + std::string mCurrentMediaURL; // The most current media url from the plugin (via the "location changed" or "navigate complete" events). S32 mLastMouseX; // save the last mouse coord we get, so when we lose capture we can simulate a mouseup at that point. S32 mLastMouseY; S32 mMediaWidth; @@ -298,6 +322,8 @@ public: bool mNeedsMuteCheck; int mPreviousMediaState; F64 mPreviousMediaTime; + bool mIsDisabled; + S32 mProximity; private: BOOL mIsUpdated ; diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index 5d0b77d4fb..2f7040aaa3 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -48,6 +48,10 @@ #include "llviewerparcelmgr.h" #include "llweb.h" #include "llmediaentry.h" +#include "llkeyboard.h" +#include "lltoolmgr.h" +#include "llvovolume.h" + // // LLViewerMediaFocus // @@ -114,13 +118,16 @@ void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 fac } else { - if(mFocusedImplID != LLUUID::null) + if(mFocusedImplID.notNull()) { if(mMediaControls.get()) { mMediaControls.get()->resetZoomLevel(); } + } + if(hasFocus()) + { gFocusMgr.setKeyboardFocus(NULL); } @@ -298,8 +305,9 @@ BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks) // the scrollEvent() API's x and y are not the same as handleScrollWheel's x and y. // The latter is the position of the mouse at the time of the event // The former is the 'scroll amount' in x and y, respectively. - // All we have for 'scroll amount' here is 'clicks', and no mask. - media_impl->getMediaPlugin()->scrollEvent(0, clicks, /*mask*/0); + // All we have for 'scroll amount' here is 'clicks'. + // We're also not passed the keyboard modifier mask, but we can get that from gKeyboard. + media_impl->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE)); retval = TRUE; } return retval; @@ -307,6 +315,30 @@ BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks) void LLViewerMediaFocus::update() { + if(mFocusedImplID.notNull() || mFocusedObjectID.notNull()) + { + // We have a focused impl/face. + if(!getFocus()) + { + // We've lost keyboard focus -- check to see whether the media controls have it + if(mMediaControls.get() && mMediaControls.get()->hasFocus()) + { + // the media controls have focus -- don't clear. + } + else + { + // Someone else has focus -- back off. + clearFocus(); + } + } + else if(LLToolMgr::getInstance()->inBuildMode()) + { + // Build tools are selected -- clear focus. + clearFocus(); + } + } + + LLViewerMediaImpl *media_impl = getFocusedMediaImpl(); LLViewerObject *viewer_object = getFocusedObject(); S32 face = mFocusedObjectFace; @@ -442,3 +474,46 @@ LLViewerObject* LLViewerMediaFocus::getHoverObject() { return gObjectList.findObject(mHoverObjectID); } + +void LLViewerMediaFocus::focusZoomOnMedia(LLUUID media_id) +{ + LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(media_id); + + if(impl) + { + // Get the first object from the media impl's object list. This is completely arbitrary, but should suffice. + LLVOVolume *obj = impl->getSomeObject(); + if(obj) + { + // This media is attached to at least one object. Figure out which face it's on. + S32 face = obj->getFaceIndexWithMediaImpl(impl, -1); + + // We don't have a proper pick normal here, and finding a face's real normal is... complicated. + // For now, use +z to look at the top of the object. + LLVector3 normal(0.0f, 0.0f, 1.0f); + + // Attempt to focus/zoom on that face. + setFocusFace(obj, face, impl, normal); + + if(mMediaControls.get()) + { + mMediaControls.get()->resetZoomLevel(); + mMediaControls.get()->nextZoomLevel(); + } + } + } +} + +LLUUID LLViewerMediaFocus::getControlsMediaID() +{ + if(getFocusedMediaImpl()) + { + return mFocusedImplID; + } + else if(getHoverMediaImpl()) + { + return mHoverImplID; + } + + return LLUUID::null; +} diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h index c1179de39d..e5f36d341c 100644 --- a/indra/newview/llviewermediafocus.h +++ b/indra/newview/llviewermediafocus.h @@ -81,6 +81,12 @@ public: LLViewerMediaImpl* getHoverMediaImpl(); LLViewerObject* getHoverObject(); S32 getHoverFace() { return mHoverObjectFace; } + + // Try to focus/zoom on the specified media (if it's on an object in world). + void focusZoomOnMedia(LLUUID media_id); + + // Return the ID of the media instance the controls are currently attached to (either focus or hover). + LLUUID getControlsMediaID(); protected: /*virtual*/ void onFocusReceived(); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 0a30b0069e..8b66341d52 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1,5723 +1,5726 @@ -/**
- * @file llviewermessage.cpp
- * @brief Dumping ground for viewer-side message system callbacks.
- *
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-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 "llviewermessage.h"
-
-#include <deque>
-
-#include "llaudioengine.h"
-#include "indra_constants.h"
-#include "lscript_byteformat.h"
-#include "mean_collision_data.h"
-#include "llfloaterbump.h"
-#include "llassetstorage.h"
-#include "llcachename.h"
-#include "llchat.h"
-#include "lldbstrings.h"
-#include "lleconomy.h"
-#include "llfilepicker.h"
-#include "llfloaterreg.h"
-#include "llfocusmgr.h"
-#include "llfollowcamparams.h"
-#include "llinstantmessage.h"
-#include "llquantize.h"
-#include "llregionflags.h"
-#include "llregionhandle.h"
-#include "llsdserialize.h"
-#include "llstring.h"
-#include "llteleportflags.h"
-#include "lltracker.h"
-#include "lltransactionflags.h"
-#include "llxfermanager.h"
-#include "message.h"
-#include "sound_ids.h"
-#include "lltimer.h"
-#include "llmd5.h"
-
-#include "llagent.h"
-#include "llcallingcard.h"
-#include "llconsole.h"
-#include "llvieweraudio.h"
-#include "llviewercontrol.h"
-#include "lldrawpool.h"
-#include "llfirstuse.h"
-#include "llfloateranimpreview.h"
-#include "llfloaterbuycurrency.h"
-#include "llfloaterbuyland.h"
-#include "llfloaterchat.h"
-#include "llfloaterimagepreview.h"
-#include "llfloaterland.h"
-#include "llfloaterregioninfo.h"
-#include "llfloaterlandholdings.h"
-#include "llurldispatcher.h"
-#include "llfloaterpostcard.h"
-#include "llfloaterpreference.h"
-#include "llfollowcam.h"
-#include "llgroupnotify.h"
-#include "llhudeffect.h"
-#include "llhudeffecttrail.h"
-#include "llhudmanager.h"
-#include "llimpanel.h"
-#include "llinventorymodel.h"
-#include "llinventorypanel.h"
-#include "llfloaterinventory.h"
-#include "llmenugl.h"
-#include "llmoveview.h"
-#include "llmutelist.h"
-#include "llnearbychat.h"
-#include "llnotifications.h"
-#include "llnotify.h"
-#include "llpanelgrouplandmoney.h"
-#include "llpanelplaces.h"
-#include "llrecentpeople.h"
-#include "llselectmgr.h"
-#include "llsidetray.h"
-#include "llstartup.h"
-#include "llsky.h"
-#include "llslurl.h"
-#include "llstatenums.h"
-#include "llstatusbar.h"
-#include "llimview.h"
-#include "lltool.h"
-#include "lltoolbar.h"
-#include "lltoolmgr.h"
-#include "lltrans.h"
-#include "llui.h" // for make_ui_sound
-#include "lluploaddialog.h"
-#include "llviewercamera.h"
-#include "llviewergenericmessage.h"
-#include "llviewerinventory.h"
-#include "llviewermenu.h"
-#include "llviewerobject.h"
-#include "llviewerobjectlist.h"
-#include "llviewerparcelmgr.h"
-#include "llviewerpartsource.h"
-#include "llviewerregion.h"
-#include "llviewerstats.h"
-#include "llviewertexteditor.h"
-#include "llviewerthrottle.h"
-#include "llviewerwindow.h"
-#include "llvlmanager.h"
-#include "llvoavatarself.h"
-#include "llvotextbubble.h"
-#include "llweb.h"
-#include "llworld.h"
-#include "pipeline.h"
-#include "llappviewer.h"
-#include "llfloaterworldmap.h"
-#include "llviewerdisplay.h"
-#include "llkeythrottle.h"
-#include "llgroupactions.h"
-#include "llagentui.h"
-#include "llpanelblockedlist.h"
-#include "llpanelplaceinfo.h"
-
-#include <boost/tokenizer.hpp>
-#include <boost/algorithm/string/split.hpp>
-
-#if LL_WINDOWS // For Windows specific error handler
-#include "llwindebug.h" // For the invalid message handler
-#endif
-
-//#include "llnearbychathistory.h"
-#include "llnotificationmanager.h"
-
-//
-// Constants
-//
-const F32 BIRD_AUDIBLE_RADIUS = 32.0f;
-const F32 SIT_DISTANCE_FROM_TARGET = 0.25f;
-static const F32 LOGOUT_REPLY_TIME = 3.f; // Wait this long after LogoutReply before quitting.
-
-// Determine how quickly residents' scripts can issue question dialogs
-// Allow bursts of up to 5 dialogs in 10 seconds. 10*2=20 seconds recovery if throttle kicks in
-static const U32 LLREQUEST_PERMISSION_THROTTLE_LIMIT = 5; // requests
-static const F32 LLREQUEST_PERMISSION_THROTTLE_INTERVAL = 10.0f; // seconds
-
-extern BOOL gDebugClicks;
-
-// function prototypes
-void open_offer(const std::vector<LLUUID>& items, const std::string& from_name);
-bool check_offer_throttle(const std::string& from_name, bool check_only);
-
-//inventory offer throttle globals
-LLFrameTimer gThrottleTimer;
-const U32 OFFER_THROTTLE_MAX_COUNT=5; //number of items per time period
-const F32 OFFER_THROTTLE_TIME=10.f; //time period in seconds
-
-//script permissions
-const std::string SCRIPT_QUESTIONS[SCRIPT_PERMISSION_EOF] =
- {
- "ScriptTakeMoney",
- "ActOnControlInputs",
- "RemapControlInputs",
- "AnimateYourAvatar",
- "AttachToYourAvatar",
- "ReleaseOwnership",
- "LinkAndDelink",
- "AddAndRemoveJoints",
- "ChangePermissions",
- "TrackYourCamera",
- "ControlYourCamera"
- };
-
-const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] =
-{
- TRUE, // ScriptTakeMoney,
- FALSE, // ActOnControlInputs
- FALSE, // RemapControlInputs
- FALSE, // AnimateYourAvatar
- FALSE, // AttachToYourAvatar
- FALSE, // ReleaseOwnership,
- FALSE, // LinkAndDelink,
- FALSE, // AddAndRemoveJoints
- FALSE, // ChangePermissions
- FALSE, // TrackYourCamera,
- FALSE // ControlYourCamera
-};
-
-bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
- LLUUID fid;
- LLMessageSystem* msg = gMessageSystem;
- const LLSD& payload = notification["payload"];
-
- // add friend to recent people list
- LLRecentPeople::instance().add(payload["from_id"]);
-
- switch(option)
- {
- case 0:
- // accept
- LLAvatarTracker::formFriendship(payload["from_id"]);
-
- fid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
-
- // This will also trigger an onlinenotification if the user is online
- msg->newMessageFast(_PREHASH_AcceptFriendship);
- 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->nextBlockFast(_PREHASH_FolderData);
- msg->addUUIDFast(_PREHASH_FolderID, fid);
- 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;
- default:
- // close button probably, possibly timed out
- break;
- }
-
- return false;
-}
-static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback);
-static LLNotificationFunctorRegistration friendship_offer_callback_reg_nm("OfferFriendshipNoMessage", friendship_offer_callback);
-
-//const char BUSY_AUTO_RESPONSE[] = "The Resident you messaged is in 'busy mode' which means they have "
-// "requested not to be disturbed. Your message will still be shown in their IM "
-// "panel for later viewing.";
-
-//
-// Functions
-//
-
-void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_group,
- S32 trx_type, const std::string& desc)
-{
- if(0 == amount || !region) return;
- amount = abs(amount);
- LL_INFOS("Messaging") << "give_money(" << uuid << "," << amount << ")"<< LL_ENDL;
- if(can_afford_transaction(amount))
- {
-// gStatusBar->debitBalance(amount);
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_MoneyTransferRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_MoneyData);
- msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID() );
- msg->addUUIDFast(_PREHASH_DestID, uuid);
- msg->addU8Fast(_PREHASH_Flags, pack_transaction_flags(FALSE, is_group));
- msg->addS32Fast(_PREHASH_Amount, amount);
- msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY);
- msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY);
- msg->addS32Fast(_PREHASH_TransactionType, trx_type );
- msg->addStringFast(_PREHASH_Description, desc);
- msg->sendReliable(region->getHost());
- }
- else
- {
- LLFloaterBuyCurrency::buyCurrency("Giving", amount);
- }
-}
-
-void send_complete_agent_movement(const LLHost& sim_host)
-{
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_CompleteAgentMovement);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addU32Fast(_PREHASH_CircuitCode, msg->mOurCircuitCode);
- msg->sendReliable(sim_host);
-}
-
-void process_logout_reply(LLMessageSystem* msg, void**)
-{
- // The server has told us it's ok to quit.
- LL_DEBUGS("Messaging") << "process_logout_reply" << LL_ENDL;
-
- LLUUID agent_id;
- msg->getUUID("AgentData", "AgentID", agent_id);
- LLUUID session_id;
- msg->getUUID("AgentData", "SessionID", session_id);
- if((agent_id != gAgent.getID()) || (session_id != gAgent.getSessionID()))
- {
- LL_WARNS("Messaging") << "Bogus Logout Reply" << LL_ENDL;
- }
-
- LLInventoryModel::update_map_t parents;
- S32 count = msg->getNumberOfBlocksFast( _PREHASH_InventoryData );
- for(S32 i = 0; i < count; ++i)
- {
- LLUUID item_id;
- msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id, i);
-
- if( (1 == count) && item_id.isNull() )
- {
- // Detect dummy item. Indicates an empty list.
- break;
- }
-
- // We do not need to track the asset ids, just account for an
- // updated inventory version.
- LL_INFOS("Messaging") << "process_logout_reply itemID=" << item_id << LL_ENDL;
- LLInventoryItem* item = gInventory.getItem( item_id );
- if( item )
- {
- parents[item->getParentUUID()] = 0;
- gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item_id);
- }
- else
- {
- LL_INFOS("Messaging") << "process_logout_reply item not found: " << item_id << LL_ENDL;
- }
- }
- LLAppViewer::instance()->forceQuit();
-}
-
-void process_layer_data(LLMessageSystem *mesgsys, void **user_data)
-{
- LLViewerRegion *regionp = LLWorld::getInstance()->getRegion(mesgsys->getSender());
-
- if (!regionp || gNoRender)
- {
- return;
- }
-
-
- S32 size;
- S8 type;
-
- mesgsys->getS8Fast(_PREHASH_LayerID, _PREHASH_Type, type);
- size = mesgsys->getSizeFast(_PREHASH_LayerData, _PREHASH_Data);
- if (0 == size)
- {
- LL_WARNS("Messaging") << "Layer data has zero size." << LL_ENDL;
- return;
- }
- if (size < 0)
- {
- // getSizeFast() is probably trying to tell us about an error
- LL_WARNS("Messaging") << "getSizeFast() returned negative result: "
- << size
- << LL_ENDL;
- return;
- }
- U8 *datap = new U8[size];
- mesgsys->getBinaryDataFast(_PREHASH_LayerData, _PREHASH_Data, datap, size);
- LLVLData *vl_datap = new LLVLData(regionp, type, datap, size);
- if (mesgsys->getReceiveCompressedSize())
- {
- gVLManager.addLayerData(vl_datap, mesgsys->getReceiveCompressedSize());
- }
- else
- {
- gVLManager.addLayerData(vl_datap, mesgsys->getReceiveSize());
- }
-}
-
-// S32 exported_object_count = 0;
-// S32 exported_image_count = 0;
-// S32 current_object_count = 0;
-// S32 current_image_count = 0;
-
-// extern LLNotifyBox *gExporterNotify;
-// extern LLUUID gExporterRequestID;
-// extern std::string gExportDirectory;
-
-// extern LLUploadDialog *gExportDialog;
-
-// std::string gExportedFile;
-
-// std::map<LLUUID, std::string> gImageChecksums;
-
-// void export_complete()
-// {
-// LLUploadDialog::modalUploadFinished();
-// gExporterRequestID.setNull();
-// gExportDirectory = "";
-
-// LLFILE* fXML = LLFile::fopen(gExportedFile, "rb"); /* Flawfinder: ignore */
-// fseek(fXML, 0, SEEK_END);
-// long length = ftell(fXML);
-// fseek(fXML, 0, SEEK_SET);
-// U8 *buffer = new U8[length + 1];
-// size_t nread = fread(buffer, 1, length, fXML);
-// if (nread < (size_t) length)
-// {
-// LL_WARNS("Messaging") << "Short read" << LL_ENDL;
-// }
-// buffer[nread] = '\0';
-// fclose(fXML);
-
-// char *pos = (char *)buffer;
-// while ((pos = strstr(pos+1, "<sl:image ")) != 0)
-// {
-// char *pos_check = strstr(pos, "checksum=\"");
-
-// if (pos_check)
-// {
-// char *pos_uuid = strstr(pos_check, "\">");
-
-// if (pos_uuid)
-// {
-// char image_uuid_str[UUID_STR_SIZE]; /* Flawfinder: ignore */
-// memcpy(image_uuid_str, pos_uuid+2, UUID_STR_SIZE-1); /* Flawfinder: ignore */
-// image_uuid_str[UUID_STR_SIZE-1] = 0;
-
-// LLUUID image_uuid(image_uuid_str);
-
-// LL_INFOS("Messaging") << "Found UUID: " << image_uuid << LL_ENDL;
-
-// std::map<LLUUID, std::string>::iterator itor = gImageChecksums.find(image_uuid);
-// if (itor != gImageChecksums.end())
-// {
-// LL_INFOS("Messaging") << "Replacing with checksum: " << itor->second << LL_ENDL;
-// if (!itor->second.empty())
-// {
-// memcpy(&pos_check[10], itor->second.c_str(), 32); /* Flawfinder: ignore */
-// }
-// }
-// }
-// }
-// }
-
-// LLFILE* fXMLOut = LLFile::fopen(gExportedFile, "wb"); /* Flawfinder: ignore */
-// if (fwrite(buffer, 1, length, fXMLOut) != length)
-// {
-// LL_WARNS("Messaging") << "Short write" << LL_ENDL;
-// }
-// fclose(fXMLOut);
-
-// delete [] buffer;
-// }
-
-
-// void exported_item_complete(const LLTSCode status, void *user_data)
-// {
-// //std::string *filename = (std::string *)user_data;
-
-// if (status < LLTS_OK)
-// {
-// LL_WARNS("Messaging") << "Export failed!" << LL_ENDL;
-// }
-// else
-// {
-// ++current_object_count;
-// if (current_image_count == exported_image_count && current_object_count == exported_object_count)
-// {
-// LL_INFOS("Messaging") << "*** Export complete ***" << LL_ENDL;
-
-// export_complete();
-// }
-// else
-// {
-// gExportDialog->setMessage(llformat("Exported %d/%d object files, %d/%d textures.", current_object_count, exported_object_count, current_image_count, exported_image_count));
-// }
-// }
-// }
-
-// struct exported_image_info
-// {
-// LLUUID image_id;
-// std::string filename;
-// U32 image_num;
-// };
-
-// void exported_j2c_complete(const LLTSCode status, void *user_data)
-// {
-// exported_image_info *info = (exported_image_info *)user_data;
-// LLUUID image_id = info->image_id;
-// U32 image_num = info->image_num;
-// std::string filename = info->filename;
-// delete info;
-
-// if (status < LLTS_OK)
-// {
-// LL_WARNS("Messaging") << "Image download failed!" << LL_ENDL;
-// }
-// else
-// {
-// LLFILE* fIn = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */
-// if (fIn)
-// {
-// LLPointer<LLImageJ2C> ImageUtility = new LLImageJ2C;
-// LLPointer<LLImageTGA> TargaUtility = new LLImageTGA;
-
-// fseek(fIn, 0, SEEK_END);
-// S32 length = ftell(fIn);
-// fseek(fIn, 0, SEEK_SET);
-// U8 *buffer = ImageUtility->allocateData(length);
-// if (fread(buffer, 1, length, fIn) != length)
-// {
-// LL_WARNS("Messaging") << "Short read" << LL_ENDL;
-// }
-// fclose(fIn);
-// LLFile::remove(filename);
-
-// // Convert to TGA
-// LLPointer<LLImageRaw> image = new LLImageRaw();
-
-// ImageUtility->updateData();
-// ImageUtility->decode(image, 100000.0f);
-
-// TargaUtility->encode(image);
-// U8 *data = TargaUtility->getData();
-// S32 data_size = TargaUtility->getDataSize();
-
-// std::string file_path = gDirUtilp->getDirName(filename);
-
-// std::string output_file = llformat("%s/image-%03d.tga", file_path.c_str(), image_num);//filename;
-// //S32 name_len = output_file.length();
-// //strcpy(&output_file[name_len-3], "tga");
-// LLFILE* fOut = LLFile::fopen(output_file, "wb"); /* Flawfinder: ignore */
-// char md5_hash_string[33]; /* Flawfinder: ignore */
-// strcpy(md5_hash_string, "00000000000000000000000000000000"); /* Flawfinder: ignore */
-// if (fOut)
-// {
-// if (fwrite(data, 1, data_size, fOut) != data_size)
-// {
-// LL_WARNS("Messaging") << "Short write" << LL_ENDL;
-// }
-// fseek(fOut, 0, SEEK_SET);
-// fclose(fOut);
-// fOut = LLFile::fopen(output_file, "rb"); /* Flawfinder: ignore */
-// LLMD5 my_md5_hash(fOut);
-// my_md5_hash.hex_digest(md5_hash_string);
-// }
-
-// gImageChecksums.insert(std::pair<LLUUID, std::string>(image_id, md5_hash_string));
-// }
-// }
-
-// ++current_image_count;
-// if (current_image_count == exported_image_count && current_object_count == exported_object_count)
-// {
-// LL_INFOS("Messaging") << "*** Export textures complete ***" << LL_ENDL;
-// export_complete();
-// }
-// else
-// {
-// gExportDialog->setMessage(llformat("Exported %d/%d object files, %d/%d textures.", current_object_count, exported_object_count, current_image_count, exported_image_count));
-// }
-//}
-
-void process_derez_ack(LLMessageSystem*, void**)
-{
- if(gViewerWindow) gViewerWindow->getWindow()->decBusyCount();
-}
-
-void process_places_reply(LLMessageSystem* msg, void** data)
-{
- LLUUID query_id;
-
- msg->getUUID("AgentData", "QueryID", query_id);
- if (query_id.isNull())
- {
- LLFloaterLandHoldings::processPlacesReply(msg, data);
- }
- else if(gAgent.isInGroup(query_id))
- {
- LLPanelGroupLandMoney::processPlacesReply(msg, data);
- }
- else
- {
- LL_WARNS("Messaging") << "Got invalid PlacesReply message" << LL_ENDL;
- }
-}
-
-void send_sound_trigger(const LLUUID& sound_id, F32 gain)
-{
- if (sound_id.isNull() || gAgent.getRegion() == NULL)
- {
- // disconnected agent or zero guids don't get sent (no sound)
- return;
- }
-
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_SoundTrigger);
- msg->nextBlockFast(_PREHASH_SoundData);
- msg->addUUIDFast(_PREHASH_SoundID, sound_id);
- // Client untrusted, ids set on sim
- msg->addUUIDFast(_PREHASH_OwnerID, LLUUID::null );
- msg->addUUIDFast(_PREHASH_ObjectID, LLUUID::null );
- msg->addUUIDFast(_PREHASH_ParentID, LLUUID::null );
-
- msg->addU64Fast(_PREHASH_Handle, gAgent.getRegion()->getHandle());
-
- LLVector3 position = gAgent.getPositionAgent();
- msg->addVector3Fast(_PREHASH_Position, position);
- msg->addF32Fast(_PREHASH_Gain, gain);
-
- gAgent.sendMessage();
-}
-
-bool join_group_response(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
- BOOL delete_context_data = TRUE;
- bool accept_invite = false;
-
- LLUUID group_id = notification["payload"]["group_id"].asUUID();
- LLUUID transaction_id = notification["payload"]["transaction_id"].asUUID();
- std::string name = notification["payload"]["name"].asString();
- std::string message = notification["payload"]["message"].asString();
- S32 fee = notification["payload"]["fee"].asInteger();
-
- if (option == 2 && !group_id.isNull())
- {
- LLGroupActions::show(group_id);
- LLSD args;
- args["MESSAGE"] = message;
- LLNotifications::instance().add("JoinGroup", args, notification["payload"]);
- return false;
- }
- if(option == 0 && !group_id.isNull())
- {
- // check for promotion or demotion.
- S32 max_groups = MAX_AGENT_GROUPS;
- if(gAgent.isInGroup(group_id)) ++max_groups;
-
- if(gAgent.mGroups.count() < max_groups)
- {
- accept_invite = true;
- }
- else
- {
- delete_context_data = FALSE;
- LLSD args;
- args["NAME"] = name;
- args["INVITE"] = message;
- LLNotifications::instance().add("JoinedTooManyGroupsMember", args, notification["payload"]);
- }
- }
-
- if (accept_invite)
- {
- // If there is a fee to join this group, make
- // sure the user is sure they want to join.
- if (fee > 0)
- {
- delete_context_data = FALSE;
- LLSD args;
- args["COST"] = llformat("%d", fee);
- // Set the fee for next time to 0, so that we don't keep
- // asking about a fee.
- LLSD next_payload = notification["payload"];
- next_payload["fee"] = 0;
- LLNotifications::instance().add("JoinGroupCanAfford",
- args,
- next_payload);
- }
- else
- {
- send_improved_im(group_id,
- std::string("name"),
- std::string("message"),
- IM_ONLINE,
- IM_GROUP_INVITATION_ACCEPT,
- transaction_id);
- }
- }
- else
- {
- send_improved_im(group_id,
- std::string("name"),
- std::string("message"),
- IM_ONLINE,
- IM_GROUP_INVITATION_DECLINE,
- transaction_id);
- }
-
- return false;
-}
-static LLNotificationFunctorRegistration jgr_1("JoinGroup", join_group_response);
-static LLNotificationFunctorRegistration jgr_2("JoinedTooManyGroupsMember", join_group_response);
-static LLNotificationFunctorRegistration jgr_3("JoinGroupCanAfford", join_group_response);
-
-
-//-----------------------------------------------------------------------------
-// Instant Message
-//-----------------------------------------------------------------------------
-class LLOpenAgentOffer : public LLInventoryFetchObserver
-{
-public:
- LLOpenAgentOffer(const std::string& from_name) : mFromName(from_name) {}
- /*virtual*/ void done()
- {
- open_offer(mComplete, mFromName);
- gInventory.removeObserver(this);
- delete this;
- }
-private:
- std::string mFromName;
-};
-
-//unlike the FetchObserver for AgentOffer, we only make one
-//instance of the AddedObserver for TaskOffers
-//and it never dies. We do this because we don't know the UUID of
-//task offers until they are accepted, so we don't wouldn't
-//know what to watch for, so instead we just watch for all additions.
-class LLOpenTaskOffer : public LLInventoryAddedObserver
-{
-protected:
- /*virtual*/ void done()
- {
- open_offer(mAdded, "");
- mAdded.clear();
- }
- };
-
-//one global instance to bind them
-LLOpenTaskOffer* gNewInventoryObserver=NULL;
-
-void start_new_inventory_observer()
-{
- if (!gNewInventoryObserver) //task offer observer
- {
- // Observer is deleted by gInventory
- gNewInventoryObserver = new LLOpenTaskOffer;
- gInventory.addObserver(gNewInventoryObserver);
- }
-}
-
-class LLDiscardAgentOffer : public LLInventoryFetchComboObserver
-{
-public:
- LLDiscardAgentOffer(const LLUUID& folder_id, const LLUUID& object_id) :
- mFolderID(folder_id),
- mObjectID(object_id) {}
- virtual ~LLDiscardAgentOffer() {}
- virtual void done()
- {
- LL_DEBUGS("Messaging") << "LLDiscardAgentOffer::done()" << LL_ENDL;
- LLUUID trash_id;
- trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
- bool notify = false;
- if(trash_id.notNull() && mObjectID.notNull())
- {
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(mFolderID, -1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
- gInventory.moveObject(mObjectID, trash_id);
- LLInventoryObject* obj = gInventory.getObject(mObjectID);
- if(obj)
- {
- // no need to restamp since this is already a freshly
- // stamped item.
- obj->updateParentOnServer(FALSE);
- notify = true;
- }
- }
- else
- {
- LL_WARNS("Messaging") << "DiscardAgentOffer unable to find: "
- << (trash_id.isNull() ? "trash " : "")
- << (mObjectID.isNull() ? "object" : "") << LL_ENDL;
- }
- gInventory.removeObserver(this);
- if(notify)
- {
- gInventory.notifyObservers();
- }
- delete this;
- }
-protected:
- LLUUID mFolderID;
- LLUUID mObjectID;
-};
-
-
-//Returns TRUE if we are OK, FALSE if we are throttled
-//Set check_only true if you want to know the throttle status
-//without registering a hit
-bool check_offer_throttle(const std::string& from_name, bool check_only)
-{
- static U32 throttle_count;
- static bool throttle_logged;
- LLChat chat;
- std::string log_message;
-
- if (!gSavedSettings.getBOOL("ShowNewInventory"))
- return false;
-
- if (check_only)
- {
- return gThrottleTimer.hasExpired();
- }
-
- if(gThrottleTimer.checkExpirationAndReset(OFFER_THROTTLE_TIME))
- {
- LL_DEBUGS("Messaging") << "Throttle Expired" << LL_ENDL;
- throttle_count=1;
- throttle_logged=false;
- return true;
- }
- else //has not expired
- {
- LL_DEBUGS("Messaging") << "Throttle Not Expired, Count: " << throttle_count << LL_ENDL;
- // When downloading the initial inventory we get a lot of new items
- // coming in and can't tell that from spam.
- if (LLStartUp::getStartupState() >= STATE_STARTED
- && throttle_count >= OFFER_THROTTLE_MAX_COUNT)
- {
- if (!throttle_logged)
- {
- // Use the name of the last item giver, who is probably the person
- // spamming you.
- std::ostringstream message;
- message << LLAppViewer::instance()->getSecondLifeTitle();
- if (!from_name.empty())
- {
- message << ": Items coming in too fast from " << from_name;
- }
- else
- {
- message << ": Items coming in too fast";
- }
- message << ", automatic preview disabled for "
- << OFFER_THROTTLE_TIME << " seconds.";
- chat.mText = message.str();
- //this is kinda important, so actually put it on screen
- LLFloaterChat::addChat(chat, FALSE, FALSE);
- throttle_logged=true;
- }
- return false;
- }
- else
- {
- throttle_count++;
- return true;
- }
- }
-}
-
-void open_offer(const std::vector<LLUUID>& items, const std::string& from_name)
-{
- std::vector<LLUUID>::const_iterator it = items.begin();
- std::vector<LLUUID>::const_iterator end = items.end();
- LLUUID trash_id(gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH));
- LLInventoryItem* item;
- for(; it != end; ++it)
- {
- const LLUUID& id = *it;
- item = gInventory.getItem(id);
- if(!item)
- {
- LL_WARNS("Messaging") << "Unable to show inventory item: " << id << LL_ENDL;
- continue;
- }
- if(gInventory.isObjectDescendentOf(id, trash_id))
- {
- continue;
- }
- LLAssetType::EType asset_type = item->getType();
-
- //if we are throttled, don't display them
- if (check_offer_throttle(from_name, false))
- {
- // If we opened this ourselves, focus it
- BOOL take_focus = from_name.empty() ? TAKE_FOCUS_YES : TAKE_FOCUS_NO;
- switch(asset_type)
- {
- case LLAssetType::AT_NOTECARD:
- LLFloaterReg::showInstance("preview_notecard", LLSD(id), take_focus);
- break;
- case LLAssetType::AT_LANDMARK:
- {
- LLInventoryCategory* parent_folder = gInventory.getCategory(item->getParentUUID());
- LLSD args;
- args["LANDMARK_NAME"] = item->getName();
- args["FOLDER_NAME"] = std::string(parent_folder ? parent_folder->getName() : "unknown");
- LLNotifications::instance().add("LandmarkCreated", args);
-
- // Created landmark is passed to Places panel to allow its editing.
- LLPanelPlaces *panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->showPanel("panel_places", LLSD()));
- if (panel)
- {
- panel->setItem(item);
- }
- }
- break;
- case LLAssetType::AT_TEXTURE:
- LLFloaterReg::showInstance("preview_texture", LLSD(id), take_focus);
- break;
- default:
- break;
- }
- }
- //highlight item, if it's not in the trash or lost+found
-
- // Don't auto-open the inventory floater
- LLFloaterInventory* view = NULL;
- if(gSavedSettings.getBOOL("ShowInInventory") &&
- asset_type != LLAssetType::AT_CALLINGCARD &&
- item->getInventoryType() != LLInventoryType::IT_ATTACHMENT &&
- !from_name.empty())
- {
- view = LLFloaterInventory::showAgentInventory();
- }
- else
- {
- view = LLFloaterInventory::getActiveInventory();
- }
- if(!view)
- {
- return;
- }
-
- //Trash Check
- LLUUID trash_id;
- trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
- if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
- {
- return;
- }
- LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
- //BOOL inventory_has_focus = gFocusMgr.childHasKeyboardFocus(view);
- BOOL user_is_away = gAwayTimer.getStarted();
-
- // don't select lost and found items if the user is active
- if (gInventory.isObjectDescendentOf(item->getUUID(), lost_and_found_id)
- && !user_is_away)
- {
- return;
- }
-
- //Not sure about this check. Could make it easy to miss incoming items.
- //don't dick with highlight while the user is working
- //if(inventory_has_focus && !user_is_away)
- // break;
- LL_DEBUGS("Messaging") << "Highlighting" << item->getUUID() << LL_ENDL;
- //highlight item
-
- if (view->getPanel())
- {
- LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus();
- view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO);
- gFocusMgr.setKeyboardFocus(focus_ctrl);
- }
- }
-}
-
-void inventory_offer_mute_callback(const LLUUID& blocked_id,
- const std::string& first_name,
- const std::string& last_name,
- BOOL is_group)
-{
- std::string from_name;
- LLMute::EType type;
-
- if (is_group)
- {
- type = LLMute::GROUP;
- from_name = first_name;
- }
- else
- {
- type = LLMute::AGENT;
- from_name = first_name + " " + last_name;
- }
-
- LLMute mute(blocked_id, from_name, type);
- if (LLMuteList::getInstance()->add(mute))
- {
- LLPanelBlockedList::showPanelAndSelect(blocked_id);
- }
-
- // purge the message queue of any previously queued inventory offers from the same source.
- class OfferMatcher : public LLNotifyBoxView::Matcher
- {
- public:
- OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {}
- BOOL matches(const LLNotificationPtr notification) const
- {
- if(notification->getName() == "ObjectGiveItem"
- || notification->getName() == "ObjectGiveItemUnknownUser"
- || notification->getName() == "UserGiveItem")
- {
- return (notification->getPayload()["from_id"].asUUID() == blocked_id);
- }
- return FALSE;
- }
- private:
- const LLUUID& blocked_id;
- };
- gNotifyBoxView->purgeMessagesMatching(OfferMatcher(blocked_id));
-}
-
-LLOfferInfo::LLOfferInfo(const LLSD& sd)
-{
- mIM = (EInstantMessage)sd["im_type"].asInteger();
- mFromID = sd["from_id"].asUUID();
- mFromGroup = sd["from_group"].asBoolean();
- mFromObject = sd["from_object"].asBoolean();
- mTransactionID = sd["transaction_id"].asUUID();
- mFolderID = sd["folder_id"].asUUID();
- mObjectID = sd["object_id"].asUUID();
- mType = LLAssetType::lookup(sd["type"].asString().c_str());
- mFromName = sd["from_name"].asString();
- mDesc = sd["description"].asString();
- mHost = LLHost(sd["sender"].asString());
-}
-
-LLSD LLOfferInfo::asLLSD()
-{
- LLSD sd;
- sd["im_type"] = mIM;
- sd["from_id"] = mFromID;
- sd["from_group"] = mFromGroup;
- sd["from_object"] = mFromObject;
- sd["transaction_id"] = mTransactionID;
- sd["folder_id"] = mFolderID;
- sd["object_id"] = mObjectID;
- sd["type"] = LLAssetType::lookup(mType);
- sd["from_name"] = mFromName;
- sd["description"] = mDesc;
- sd["sender"] = mHost.getIPandPort();
- return sd;
-}
-
-bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& response)
- {
- LLChat chat;
- std::string log_message;
- S32 button = LLNotification::getSelectedOption(notification, response);
-
- // For muting, we need to add the mute, then decline the offer.
- // This must be done here because:
- // * callback may be called immediately,
- // * adding the mute sends a message,
- // * we can't build two messages at once.
- if (2 == button)
- {
- gCacheName->get(mFromID, mFromGroup, &inventory_offer_mute_callback);
- }
-
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_MessageBlock);
- msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
- msg->addUUIDFast(_PREHASH_ToAgentID, mFromID);
- msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
- msg->addUUIDFast(_PREHASH_ID, mTransactionID);
- msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
- std::string name;
- LLAgentUI::buildFullname(name);
- msg->addStringFast(_PREHASH_FromAgentName, name);
- msg->addStringFast(_PREHASH_Message, "");
- msg->addU32Fast(_PREHASH_ParentEstateID, 0);
- msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
- msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
- LLInventoryObserver* opener = NULL;
- LLViewerInventoryCategory* catp = NULL;
- catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID);
- LLViewerInventoryItem* itemp = NULL;
- if(!catp)
- {
- itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID);
- }
-
- std::string from_string; // Used in the pop-up.
- std::string chatHistory_string; // Used in chat history.
- if (mFromObject == TRUE)
- {
- if (mFromGroup)
- {
- std::string group_name;
- if (gCacheName->getGroupName(mFromID, group_name))
- {
- from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'"
- + mFromName + LLTrans::getString("'") +" " + LLTrans::getString("InvOfferOwnedByGroup")
- + " "+ "'" + group_name + "'";
-
- chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByGroup")
- + " " + group_name + "'";
- }
- else
- {
- from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'"
- + mFromName +"'"+ " " + LLTrans::getString("InvOfferOwnedByUnknownGroup");
- chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownGroup");
- }
- }
- else
- {
- std::string first_name, last_name;
- if (gCacheName->getName(mFromID, first_name, last_name))
- {
- from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+ LLTrans::getString("'") + mFromName
- + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedBy") + first_name + " " + last_name;
- chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedBy") + " " + first_name + " " + last_name;
- }
- else
- {
- from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+LLTrans::getString("'")
- + mFromName + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedByUnknownUser");
- chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownUser");
- }
- }
- }
- else
- {
- from_string = chatHistory_string = mFromName;
- }
-
- bool busy=FALSE;
-
- switch(button)
- {
- case IOR_ACCEPT:
- // ACCEPT. The math for the dialog works, because the accept
- // for inventory_offered, task_inventory_offer or
- // group_notice_inventory is 1 greater than the offer integer value.
- // Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED,
- // or IM_GROUP_NOTICE_INVENTORY_ACCEPTED
- msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
- msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData),
- sizeof(mFolderID.mData));
- // send the message
- msg->sendReliable(mHost);
-
- //don't spam them if they are getting flooded
- if (check_offer_throttle(mFromName, true))
- {
- log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString(".");
- chat.mText = log_message;
- LLFloaterChat::addChatHistory(chat);
- }
-
- // we will want to open this item when it comes back.
- LL_DEBUGS("Messaging") << "Initializing an opener for tid: " << mTransactionID
- << LL_ENDL;
- switch (mIM)
- {
- case IM_INVENTORY_OFFERED:
- {
- // This is an offer from an agent. In this case, the back
- // end has already copied the items into your inventory,
- // so we can fetch it out of our inventory.
- LLInventoryFetchObserver::item_ref_t items;
- items.push_back(mObjectID);
- LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(from_string);
- open_agent_offer->fetchItems(items);
- if(catp || (itemp && itemp->isComplete()))
- {
- open_agent_offer->done();
- }
- else
- {
- opener = open_agent_offer;
- }
- }
- break;
- case IM_TASK_INVENTORY_OFFERED:
- case IM_GROUP_NOTICE:
- case IM_GROUP_NOTICE_REQUESTED:
- {
- // This is an offer from a task or group.
- // We don't use a new instance of an opener
- // We instead use the singular observer gOpenTaskOffer
- // Since it already exists, we don't need to actually do anything
- }
- break;
- default:
- LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;
- break;
- } // end switch (mIM)
- break;
-
- case IOR_BUSY:
- //Busy falls through to decline. Says to make busy message.
- busy=TRUE;
- case IOR_MUTE:
- // MUTE falls through to decline
- case IOR_DECLINE:
- // DECLINE. The math for the dialog works, because the decline
- // for inventory_offered, task_inventory_offer or
- // group_notice_inventory is 2 greater than the offer integer value.
- // Generates IM_INVENTORY_DECLINED, IM_TASK_INVENTORY_DECLINED,
- // or IM_GROUP_NOTICE_INVENTORY_DECLINED
- default:
- // close button probably (or any of the fall-throughs from above)
- msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 2));
- msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE);
- // send the message
- msg->sendReliable(mHost);
-
- log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +".";
- chat.mText = log_message;
- if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) ) // muting for SL-42269
- {
- chat.mMuted = TRUE;
- }
- LLFloaterChat::addChatHistory(chat);
-
- // If it's from an agent, we have to fetch the item to throw
- // it away. If it's from a task or group, just denying the
- // request will suffice to discard the item.
- if(IM_INVENTORY_OFFERED == mIM)
- {
- LLInventoryFetchComboObserver::folder_ref_t folders;
- LLInventoryFetchComboObserver::item_ref_t items;
- items.push_back(mObjectID);
- LLDiscardAgentOffer* discard_agent_offer;
- discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID);
- discard_agent_offer->fetch(folders, items);
- if(catp || (itemp && itemp->isComplete()))
- {
- discard_agent_offer->done();
- }
- else
- {
- opener = discard_agent_offer;
- }
-
- }
- if (busy && (!mFromGroup && !mFromObject))
- {
- busy_message(msg,mFromID);
- }
- break;
- }
-
- if(IM_INVENTORY_OFFERED == mIM)
- {
- // add buddy to recent people list
- LLRecentPeople::instance().add(mFromID);
- }
-
- if(opener)
- {
- gInventory.addObserver(opener);
- }
-
- delete this;
- return false;
-}
-
-
-void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
-{
- //Until throttling is implmented, busy mode should reject inventory instead of silently
- //accepting it. SEE SL-39554
- if (gAgent.getBusy())
- {
- info->forceResponse(IOR_BUSY);
- return;
- }
-
- //If muted, don't even go through the messaging stuff. Just curtail the offer here.
- if (LLMuteList::getInstance()->isMuted(info->mFromID, info->mFromName))
- {
- info->forceResponse(IOR_MUTE);
- return;
- }
-
- // Avoid the Accept/Discard dialog if the user so desires. JC
- if (gSavedSettings.getBOOL("AutoAcceptNewInventory")
- && (info->mType == LLAssetType::AT_NOTECARD
- || info->mType == LLAssetType::AT_LANDMARK
- || info->mType == LLAssetType::AT_TEXTURE))
- {
- // For certain types, just accept the items into the inventory,
- // and possibly open them on receipt depending upon "ShowNewInventory".
- info->forceResponse(IOR_ACCEPT);
- return;
- }
-
- // Strip any SLURL from the message display. (DEV-2754)
- std::string msg = info->mDesc;
- int indx = msg.find(" ( http://slurl.com/secondlife/");
- if(indx >= 0)
- {
- LLStringUtil::truncate(msg, indx);
- }
-
- LLSD args;
- args["[OBJECTNAME]"] = msg;
-
- LLSD payload;
-
- // must protect against a NULL return from lookupHumanReadable()
- std::string typestr = ll_safe_string(LLAssetType::lookupHumanReadable(info->mType));
- if (!typestr.empty())
- {
- args["OBJECTTYPE"] = typestr;
- }
- else
- {
- LL_WARNS("Messaging") << "LLAssetType::lookupHumanReadable() returned NULL - probably bad asset type: " << info->mType << LL_ENDL;
- args["OBJECTTYPE"] = "";
-
- // This seems safest, rather than propagating bogosity
- LL_WARNS("Messaging") << "Forcing an inventory-decline for probably-bad asset type." << LL_ENDL;
- info->forceResponse(IOR_DECLINE);
- return;
- }
-
- // Name cache callbacks don't store userdata, so can't save
- // off the LLOfferInfo. Argh.
- BOOL name_found = FALSE;
- if (info->mFromGroup)
- {
- std::string group_name;
- if (gCacheName->getGroupName(info->mFromID, group_name))
- {
- args["FIRST"] = group_name;
- args["LAST"] = "";
- name_found = TRUE;
- }
- }
- else
- {
- std::string first_name, last_name;
- if (gCacheName->getName(info->mFromID, first_name, last_name))
- {
- args["FIRST"] = first_name;
- args["LAST"] = last_name;
- name_found = TRUE;
- }
- }
-
- payload["from_id"] = info->mFromID;
- args["OBJECTFROMNAME"] = info->mFromName;
- args["NAME"] = info->mFromName;
-
- LLNotification::Params p("ObjectGiveItem");
- p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2));
-
- if (from_task)
- {
- p.name = name_found ? "ObjectGiveItem" : "ObjectGiveItemUnknownUser";
- }
- else
- {
- p.name = "UserGiveItem";
- }
-
- LLNotifications::instance().add(p);
-}
-
-bool lure_callback(const LLSD& notification, const LLSD& response)
-{
- S32 option = 0;
- if (response.isInteger())
- {
- option = response.asInteger();
- }
- else
- {
- option = LLNotification::getSelectedOption(notification, response);
- }
-
- LLUUID from_id = notification["payload"]["from_id"].asUUID();
- LLUUID lure_id = notification["payload"]["lure_id"].asUUID();
- BOOL godlike = notification["payload"]["godlike"].asBoolean();
-
- switch(option)
- {
- case 0:
- {
- // accept
- gAgent.teleportViaLure(lure_id, godlike);
- }
- break;
- case 1:
- default:
- // decline
- send_simple_im(from_id,
- LLStringUtil::null,
- IM_LURE_DECLINED,
- lure_id);
- break;
- }
- return false;
-}
-static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback);
-
-bool goto_url_callback(const LLSD& notification, const LLSD& response)
-{
- std::string url = notification["payload"]["url"].asString();
- S32 option = LLNotification::getSelectedOption(notification, response);
- if(1 == option)
- {
- LLWeb::loadURL(url);
- }
- return false;
-}
-static LLNotificationFunctorRegistration goto_url_callback_reg("GotoURL", goto_url_callback);
-
-void process_improved_im(LLMessageSystem *msg, void **user_data)
-{
- if (gNoRender)
- {
- return;
- }
- LLUUID from_id;
- BOOL from_group;
- LLUUID to_id;
- U8 offline;
- U8 d = 0;
- LLUUID session_id;
- U32 timestamp;
- std::string name;
- std::string message;
- U32 parent_estate_id = 0;
- LLUUID region_id;
- LLVector3 position;
- U8 binary_bucket[MTUBYTES];
- S32 binary_bucket_size;
- LLChat chat;
- std::string buffer;
-
- // *TODO: Translate - need to fix the full name to first/last (maybe)
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, from_id);
- msg->getBOOLFast(_PREHASH_MessageBlock, _PREHASH_FromGroup, from_group);
- msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ToAgentID, to_id);
- msg->getU8Fast( _PREHASH_MessageBlock, _PREHASH_Offline, offline);
- msg->getU8Fast( _PREHASH_MessageBlock, _PREHASH_Dialog, d);
- msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ID, session_id);
- msg->getU32Fast( _PREHASH_MessageBlock, _PREHASH_Timestamp, timestamp);
- //msg->getData("MessageBlock", "Count", &count);
- msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_FromAgentName, name);
- msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_Message, message);
- msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_ParentEstateID, parent_estate_id);
- msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_RegionID, region_id);
- msg->getVector3Fast(_PREHASH_MessageBlock, _PREHASH_Position, position);
- msg->getBinaryDataFast( _PREHASH_MessageBlock, _PREHASH_BinaryBucket, binary_bucket, 0, 0, MTUBYTES);
- binary_bucket_size = msg->getSizeFast(_PREHASH_MessageBlock, _PREHASH_BinaryBucket);
- EInstantMessage dialog = (EInstantMessage)d;
-
- // make sure that we don't have an empty or all-whitespace name
- LLStringUtil::trim(name);
- if (name.empty())
- {
- name = LLTrans::getString("Unnamed");
- }
-
- BOOL is_busy = gAgent.getBusy();
- BOOL is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat);
- BOOL is_linden = LLMuteList::getInstance()->isLinden(name);
- BOOL is_owned_by_me = FALSE;
- BOOL is_friend = (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL) ? false : true;
- BOOL accept_im_from_only_friend = gSavedSettings.getBOOL("VoiceCallsFriendsOnly");
-
- chat.mMuted = is_muted && !is_linden;
- chat.mFromID = from_id;
- chat.mFromName = name;
- chat.mSourceType = (from_id.isNull() || (name == std::string(SYSTEM_FROM))) ? CHAT_SOURCE_SYSTEM : CHAT_SOURCE_AGENT;
-
- LLViewerObject *source = gObjectList.findObject(session_id); //Session ID is probably the wrong thing.
- if (source)
- {
- is_owned_by_me = source->permYouOwner();
- }
-
- std::string separator_string(": ");
- int message_offset = 0;
-
- //Handle IRC styled /me messages.
- std::string prefix = message.substr(0, 4);
- if (prefix == "/me " || prefix == "/me'")
- {
- separator_string = "";
- message_offset = 3;
- }
-
- LLSD args;
- switch(dialog)
- {
- case IM_CONSOLE_AND_CHAT_HISTORY:
- // These are used for system messages, hence don't need the name,
- // as it is always "Second Life".
- // *TODO: Translate
- args["MESSAGE"] = message;
-
- // Note: don't put the message in the IM history, even though was sent
- // via the IM mechanism.
- LLNotifications::instance().add("SystemMessageTip",args);
- break;
-
- case IM_NOTHING_SPECIAL:
- // Don't show dialog, just do IM
- if (!gAgent.isGodlike()
- && gAgent.getRegion()->isPrelude()
- && to_id.isNull() )
- {
- // do nothing -- don't distract newbies in
- // Prelude with global IMs
- }
- else if (offline == IM_ONLINE && !is_linden && is_busy && name != SYSTEM_FROM)
- {
- // return a standard "busy" message, but only do it to online IM
- // (i.e. not other auto responses and not store-and-forward IM)
- if (!gIMMgr->hasSession(session_id))
- {
- // if there is not a panel for this conversation (i.e. it is a new IM conversation
- // initiated by the other party) then...
- std::string my_name;
- LLAgentUI::buildFullname(my_name);
- std::string response = gSavedPerAccountSettings.getString("BusyModeResponse2");
- pack_instant_message(
- gMessageSystem,
- gAgent.getID(),
- FALSE,
- gAgent.getSessionID(),
- from_id,
- my_name,
- response,
- IM_ONLINE,
- IM_BUSY_AUTO_RESPONSE,
- session_id);
- gAgent.sendReliableMessage();
- }
-
- // now store incoming IM in chat history
-
- buffer = message.substr(message_offset);
-
- LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
-
- // add to IM panel, but do not bother the user
- gIMMgr->addMessage(
- session_id,
- from_id,
- name,
- buffer,
- LLStringUtil::null,
- dialog,
- parent_estate_id,
- region_id,
- position,
- true);
-
- // pretend this is chat generated by self, so it does not show up on screen
- chat.mText = std::string("IM: ") + name + separator_string + message.substr(message_offset);
- LLFloaterChat::addChat( chat, TRUE, TRUE );
- }
- else if (from_id.isNull())
- {
- // Messages from "Second Life" ID don't go to IM history
- // messages which should be routed to IM window come from a user ID with name=SYSTEM_NAME
- chat.mText = name + ": " + message;
- LLFloaterChat::addChat(chat, FALSE, FALSE);
- }
- else if (to_id.isNull())
- {
- // Message to everyone from GOD
- args["NAME"] = name;
- args["MESSAGE"] = message;
- LLNotifications::instance().add("GodMessage", args);
-
- // Treat like a system message and put in chat history.
- // Claim to be from a local agent so it doesn't go into
- // console.
- chat.mText = name + separator_string + message.substr(message_offset);
- BOOL local_agent = TRUE;
- LLFloaterChat::addChat(chat, FALSE, local_agent);
- }
- else
- {
- // standard message, not from system
- std::string saved;
- if(offline == IM_OFFLINE)
- {
- saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
- }
- buffer = saved + message.substr(message_offset);
-
- LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
-
- bool mute_im = is_muted;
- if(accept_im_from_only_friend&&!is_friend)
- {
- mute_im = true;
- }
- if (!mute_im || is_linden)
- {
- gIMMgr->addMessage(
- session_id,
- from_id,
- name,
- buffer,
- LLStringUtil::null,
- dialog,
- parent_estate_id,
- region_id,
- position,
- true);
- chat.mText = std::string("IM: ") + name + separator_string + saved + message.substr(message_offset);
-
- BOOL local_agent = FALSE;
- LLFloaterChat::addChat( chat, TRUE, local_agent );
- }
- else
- {
- // muted user, so don't start an IM session, just record line in chat
- // history. Pretend the chat is from a local agent,
- // so it will go into the history but not be shown on screen.
- chat.mText = buffer;
- BOOL local_agent = TRUE;
- LLFloaterChat::addChat( chat, TRUE, local_agent );
- }
- }
- break;
-
- case IM_TYPING_START:
- {
- LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem);
- gIMMgr->processIMTypingStart(im_info);
- }
- break;
-
- case IM_TYPING_STOP:
- {
- LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem);
- gIMMgr->processIMTypingStop(im_info);
- }
- break;
-
- case IM_MESSAGEBOX:
- {
- // This is a block, modeless dialog.
- //*TODO: Translate
- args["MESSAGE"] = message;
- LLNotifications::instance().add("SystemMessage", args);
- }
- break;
- case IM_GROUP_NOTICE:
- case IM_GROUP_NOTICE_REQUESTED:
- {
- LL_INFOS("Messaging") << "Received IM_GROUP_NOTICE message." << LL_ENDL;
- // Read the binary bucket for more information.
- struct notice_bucket_header_t
- {
- U8 has_inventory;
- U8 asset_type;
- LLUUID group_id;
- };
- struct notice_bucket_full_t
- {
- struct notice_bucket_header_t header;
- U8 item_name[DB_INV_ITEM_NAME_BUF_SIZE];
- }* notice_bin_bucket;
-
- // Make sure the binary bucket is big enough to hold the header
- // and a null terminated item name.
- if ( (binary_bucket_size < (S32)((sizeof(notice_bucket_header_t) + sizeof(U8))))
- || (binary_bucket[binary_bucket_size - 1] != '\0') )
- {
- LL_WARNS("Messaging") << "Malformed group notice binary bucket" << LL_ENDL;
- break;
- }
-
- notice_bin_bucket = (struct notice_bucket_full_t*) &binary_bucket[0];
- U8 has_inventory = notice_bin_bucket->header.has_inventory;
- U8 asset_type = notice_bin_bucket->header.asset_type;
- LLUUID group_id = notice_bin_bucket->header.group_id;
- std::string item_name = ll_safe_string((const char*) notice_bin_bucket->item_name);
-
- // If there is inventory, give the user the inventory offer.
- LLOfferInfo* info = NULL;
-
- if (has_inventory)
- {
- info = new LLOfferInfo;
-
- info->mIM = IM_GROUP_NOTICE;
- info->mFromID = from_id;
- info->mFromGroup = from_group;
- info->mTransactionID = session_id;
- info->mType = (LLAssetType::EType) asset_type;
- info->mFolderID = gInventory.findCategoryUUIDForType(info->mType);
- std::string from_name;
-
- from_name += "A group member named ";
- from_name += name;
-
- info->mFromName = from_name;
- info->mDesc = item_name;
- info->mHost = msg->getSender();
- }
-
- std::string str(message);
-
- // Tokenize the string.
- // TODO: Support escaped tokens ("||" -> "|")
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("|","",boost::keep_empty_tokens);
- tokenizer tokens(str, sep);
- tokenizer::iterator iter = tokens.begin();
-
- std::string subj(*iter++);
- std::string mes(*iter++);
-
- // Send the notification down the new path.
- // For requested notices, we don't want to send the popups.
- if (dialog != IM_GROUP_NOTICE_REQUESTED)
- {
- LLSD payload;
- payload["subject"] = subj;
- payload["message"] = mes;
- payload["sender_name"] = name;
- payload["group_id"] = group_id;
- payload["inventory_name"] = item_name;
- payload["inventory_offer"] = info ? info->asLLSD() : LLSD();
-
- LLSD args;
- args["SUBJECT"] = subj;
- args["MESSAGE"] = mes;
- LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).time_stamp(timestamp));
- }
-
- // Also send down the old path for now.
- if (IM_GROUP_NOTICE_REQUESTED == dialog)
- {
-
- LLPanelGroup::showNotice(subj,mes,group_id,has_inventory,item_name,info);
- }
- }
- break;
- case IM_GROUP_INVITATION:
- {
- //if (!is_linden && (is_busy || is_muted))
- if ((is_busy || is_muted))
- {
- LLMessageSystem *msg = gMessageSystem;
- busy_message(msg,from_id);
- }
- else
- {
- LL_INFOS("Messaging") << "Received IM_GROUP_INVITATION message." << LL_ENDL;
- // Read the binary bucket for more information.
- struct invite_bucket_t
- {
- S32 membership_fee;
- LLUUID role_id;
- }* invite_bucket;
-
- // Make sure the binary bucket is the correct size.
- if (binary_bucket_size != sizeof(invite_bucket_t))
- {
- LL_WARNS("Messaging") << "Malformed group invite binary bucket" << LL_ENDL;
- break;
- }
-
- invite_bucket = (struct invite_bucket_t*) &binary_bucket[0];
- S32 membership_fee = ntohl(invite_bucket->membership_fee);
-
- LLSD payload;
- payload["transaction_id"] = session_id;
- payload["group_id"] = from_id;
- payload["name"] = name;
- payload["message"] = message;
- payload["fee"] = membership_fee;
-
- LLSD args;
- args["MESSAGE"] = message;
- LLNotifications::instance().add("JoinGroup", args, payload, join_group_response);
- }
- }
- break;
-
- case IM_INVENTORY_OFFERED:
- case IM_TASK_INVENTORY_OFFERED:
- // Someone has offered us some inventory.
- {
- LLOfferInfo* info = new LLOfferInfo;
- bool mute_im = false;
- if (IM_INVENTORY_OFFERED == dialog)
- {
- struct offer_agent_bucket_t
- {
- S8 asset_type;
- LLUUID object_id;
- }* bucketp;
-
- if (sizeof(offer_agent_bucket_t) != binary_bucket_size)
- {
- LL_WARNS("Messaging") << "Malformed inventory offer from agent" << LL_ENDL;
- break;
- }
- bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0];
- info->mType = (LLAssetType::EType) bucketp->asset_type;
- info->mObjectID = bucketp->object_id;
-
- if(accept_im_from_only_friend&&!is_friend)
- {
- mute_im = true;
- }
- }
- else
- {
- if (sizeof(S8) != binary_bucket_size)
- {
- LL_WARNS("Messaging") << "Malformed inventory offer from object" << LL_ENDL;
- break;
- }
- info->mType = (LLAssetType::EType) binary_bucket[0];
- info->mObjectID = LLUUID::null;
- }
-
- info->mIM = dialog;
- info->mFromID = from_id;
- info->mFromGroup = from_group;
- info->mTransactionID = session_id;
- info->mFolderID = gInventory.findCategoryUUIDForType(info->mType);
-
- if (dialog == IM_TASK_INVENTORY_OFFERED)
- {
- info->mFromObject = TRUE;
- }
- else
- {
- info->mFromObject = FALSE;
- }
- info->mFromName = name;
- info->mDesc = message;
- info->mHost = msg->getSender();
- //if (((is_busy && !is_owned_by_me) || is_muted))
- if ( is_muted || mute_im)
- {
- // Same as closing window
- info->forceResponse(IOR_DECLINE);
- }
- else
- {
- inventory_offer_handler(info, dialog == IM_TASK_INVENTORY_OFFERED);
- }
- }
- break;
-
- case IM_INVENTORY_ACCEPTED:
- {
- args["NAME"] = name;
- LLNotifications::instance().add("InventoryAccepted", args);
- break;
- }
- case IM_INVENTORY_DECLINED:
- {
- args["NAME"] = name;
- LLNotifications::instance().add("InventoryDeclined", args);
- break;
- }
- // TODO: _DEPRECATED suffix as part of vote removal - DEV-24856
- case IM_GROUP_VOTE:
- {
- LL_WARNS("Messaging") << "Received IM: IM_GROUP_VOTE_DEPRECATED" << LL_ENDL;
- }
- break;
-
- case IM_GROUP_ELECTION_DEPRECATED:
- {
- LL_WARNS("Messaging") << "Received IM: IM_GROUP_ELECTION_DEPRECATED" << LL_ENDL;
- }
- break;
-
- case IM_SESSION_SEND:
- {
- if (!is_linden && is_busy)
- {
- return;
- }
-
- // Only show messages if we have a session open (which
- // should happen after you get an "invitation"
- if ( !gIMMgr->hasSession(session_id) )
- {
- return;
- }
-
- // standard message, not from system
- std::string saved;
- if(offline == IM_OFFLINE)
- {
- saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
- }
- buffer = saved + message.substr(message_offset);
- BOOL is_this_agent = FALSE;
- if(from_id == gAgentID)
- {
- is_this_agent = TRUE;
- }
- gIMMgr->addMessage(
- session_id,
- from_id,
- name,
- buffer,
- ll_safe_string((char*)binary_bucket),
- IM_SESSION_INVITE,
- parent_estate_id,
- region_id,
- position,
- true);
-
- chat.mText = std::string("IM: ") + name + separator_string + saved + message.substr(message_offset);
- LLFloaterChat::addChat(chat, TRUE, is_this_agent);
- }
- break;
-
- case IM_FROM_TASK:
- {
- if (is_busy && !is_owned_by_me)
- {
- return;
- }
-
- LLSD substitutions;
- substitutions["MSG"] = message.substr(message_offset);
- LLNotifications::instance().add("ServerObjectMessage", substitutions);
- }
- break;
- case IM_FROM_TASK_AS_ALERT:
- if (is_busy && !is_owned_by_me)
- {
- return;
- }
- {
- // Construct a viewer alert for this message.
- args["NAME"] = name;
- args["MESSAGE"] = message;
- LLNotifications::instance().add("ObjectMessage", args);
- }
- break;
- case IM_BUSY_AUTO_RESPONSE:
- if (is_muted)
- {
- LL_DEBUGS("Messaging") << "Ignoring busy response from " << from_id << LL_ENDL;
- return;
- }
- else
- {
- // TODO: after LLTrans hits release, get "busy response" into translatable file
- buffer = llformat("%s (%s): %s", name.c_str(), "busy response", message.substr(message_offset).c_str());
- gIMMgr->addMessage(session_id, from_id, name, buffer);
- }
- break;
-
- case IM_LURE_USER:
- {
- if (is_muted)
- {
- return;
- }
- else if (is_busy)
- {
- busy_message(msg,from_id);
- }
- else
- {
- LLSD args;
- // *TODO: Translate -> [FIRST] [LAST] (maybe)
- args["NAME"] = name;
- args["MESSAGE"] = message;
- LLSD payload;
- payload["from_id"] = from_id;
- payload["lure_id"] = session_id;
- payload["godlike"] = FALSE;
- LLNotifications::instance().add("TeleportOffered", args, payload);
- }
- }
- break;
-
- case IM_GODLIKE_LURE_USER:
- {
- LLSD payload;
- payload["from_id"] = from_id;
- payload["lure_id"] = session_id;
- payload["godlike"] = TRUE;
- // do not show a message box, because you're about to be
- // teleported.
- LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0);
- }
- break;
-
- case IM_GOTO_URL:
- {
- LLSD args;
- // n.b. this is for URLs sent by the system, not for
- // URLs sent by scripts (i.e. llLoadURL)
- if (binary_bucket_size <= 0)
- {
- LL_WARNS("Messaging") << "bad binary_bucket_size: "
- << binary_bucket_size
- << " - aborting function." << LL_ENDL;
- return;
- }
-
- std::string url;
-
- url.assign((char*)binary_bucket, binary_bucket_size-1);
- args["MESSAGE"] = message;
- args["URL"] = url;
- LLSD payload;
- payload["url"] = url;
- LLNotifications::instance().add("GotoURL", args, payload );
- }
- break;
-
- case IM_FRIENDSHIP_OFFERED:
- {
- LLSD payload;
- payload["from_id"] = from_id;
- payload["session_id"] = session_id;;
- payload["online"] = (offline == IM_ONLINE);
- payload["sender"] = msg->getSender().getIPandPort();
-
- if (is_busy)
- {
- busy_message(msg, from_id);
- LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1);
- }
- else if (is_muted)
- {
- LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1);
- }
- else
- {
- args["[NAME]"] = name;
- if(message.empty())
- {
- //support for frienship offers from clients before July 2008
- LLNotifications::instance().add("OfferFriendshipNoMessage", args, payload);
- }
- else
- {
- args["[MESSAGE]"] = message;
- LLNotifications::instance().add("OfferFriendship", args, payload);
- }
- }
- }
- break;
-
- case IM_FRIENDSHIP_ACCEPTED:
- {
- // In the case of an offline IM, the formFriendship() may be extraneous
- // as the database should already include the relationship. But it
- // doesn't hurt for dupes.
- LLAvatarTracker::formFriendship(from_id);
-
- std::vector<std::string> strings;
- strings.push_back(from_id.asString());
- send_generic_message("requestonlinenotification", strings);
-
- args["NAME"] = name;
- LLNotifications::instance().add("FriendshipAccepted", args);
- }
- break;
-
- case IM_FRIENDSHIP_DECLINED_DEPRECATED:
- default:
- LL_WARNS("Messaging") << "Instant message calling for unknown dialog "
- << (S32)dialog << LL_ENDL;
- break;
- }
-
- LLWindow* viewer_window = gViewerWindow->getWindow();
- if (viewer_window && viewer_window->getMinimized())
- {
- viewer_window->flashIcon(5.f);
- }
-}
-
-void busy_message (LLMessageSystem* msg, LLUUID from_id)
-{
- if (gAgent.getBusy())
- {
- std::string my_name;
- LLAgentUI::buildFullname(my_name);
- std::string response = gSavedPerAccountSettings.getString("BusyModeResponse2");
- pack_instant_message(
- gMessageSystem,
- gAgent.getID(),
- FALSE,
- gAgent.getSessionID(),
- from_id,
- my_name,
- response,
- IM_ONLINE,
- IM_BUSY_AUTO_RESPONSE);
- gAgent.sendReliableMessage();
- }
-}
-
-bool callingcard_offer_callback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
- LLUUID fid;
- LLUUID from_id;
- LLMessageSystem* msg = gMessageSystem;
- switch(option)
- {
- case 0:
- // accept
- msg->newMessageFast(_PREHASH_AcceptCallingCard);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_TransactionBlock);
- msg->addUUIDFast(_PREHASH_TransactionID, notification["payload"]["transaction_id"].asUUID());
- fid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
- msg->nextBlockFast(_PREHASH_FolderData);
- msg->addUUIDFast(_PREHASH_FolderID, fid);
- msg->sendReliable(LLHost(notification["payload"]["sender"].asString()));
- break;
- case 1:
- // decline
- msg->newMessageFast(_PREHASH_DeclineCallingCard);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_TransactionBlock);
- msg->addUUIDFast(_PREHASH_TransactionID, notification["payload"]["transaction_id"].asUUID());
- msg->sendReliable(LLHost(notification["payload"]["sender"].asString()));
- busy_message(msg, notification["payload"]["source_id"].asUUID());
- break;
- default:
- // close button probably, possibly timed out
- break;
- }
-
- return false;
-}
-static LLNotificationFunctorRegistration callingcard_offer_cb_reg("OfferCallingCard", callingcard_offer_callback);
-
-void process_offer_callingcard(LLMessageSystem* msg, void**)
-{
- // someone has offered to form a friendship
- LL_DEBUGS("Messaging") << "callingcard offer" << LL_ENDL;
-
- LLUUID source_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, source_id);
- LLUUID tid;
- msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_TransactionID, tid);
-
- LLSD payload;
- payload["transaction_id"] = tid;
- payload["source_id"] = source_id;
- payload["sender"] = msg->getSender().getIPandPort();
-
- LLViewerObject* source = gObjectList.findObject(source_id);
- LLSD args;
- std::string source_name;
- if(source && source->isAvatar())
- {
- LLNameValue* nvfirst = source->getNVPair("FirstName");
- LLNameValue* nvlast = source->getNVPair("LastName");
- if (nvfirst && nvlast)
- {
- args["FIRST"] = nvfirst->getString();
- args["LAST"] = nvlast->getString();
- source_name = std::string(nvfirst->getString()) + " " + nvlast->getString();
- }
- }
-
- if(!source_name.empty())
- {
- if (gAgent.getBusy()
- || LLMuteList::getInstance()->isMuted(source_id, source_name, LLMute::flagTextChat))
- {
- // automatically decline offer
- LLNotifications::instance().forceResponse(LLNotification::Params("OfferCallingCard").payload(payload), 1);
- }
- else
- {
- LLNotifications::instance().add("OfferCallingCard", args, payload);
- }
- }
- else
- {
- LL_WARNS("Messaging") << "Calling card offer from an unknown source." << LL_ENDL;
- }
-}
-
-void process_accept_callingcard(LLMessageSystem* msg, void**)
-{
- LLNotifications::instance().add("CallingCardAccepted");
-}
-
-void process_decline_callingcard(LLMessageSystem* msg, void**)
-{
- LLNotifications::instance().add("CallingCardDeclined");
-}
-
-
-void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
-{
- LLChat chat;
- std::string mesg;
- std::string from_name;
- U8 source_temp;
- U8 type_temp;
- U8 audible_temp;
- LLColor4 color(1.0f, 1.0f, 1.0f, 1.0f);
- LLUUID from_id;
- LLUUID owner_id;
- BOOL is_owned_by_me = FALSE;
- LLViewerObject* chatter;
-
- msg->getString("ChatData", "FromName", from_name);
- chat.mFromName = from_name;
-
- msg->getUUID("ChatData", "SourceID", from_id);
- chat.mFromID = from_id;
-
- // Object owner for objects
- msg->getUUID("ChatData", "OwnerID", owner_id);
-
- msg->getU8Fast(_PREHASH_ChatData, _PREHASH_SourceType, source_temp);
- chat.mSourceType = (EChatSourceType)source_temp;
-
- msg->getU8("ChatData", "ChatType", type_temp);
- chat.mChatType = (EChatType)type_temp;
-
- msg->getU8Fast(_PREHASH_ChatData, _PREHASH_Audible, audible_temp);
- chat.mAudible = (EChatAudible)audible_temp;
-
- chat.mTime = LLFrameTimer::getElapsedSeconds();
-
- BOOL is_busy = gAgent.getBusy();
-
- BOOL is_muted = FALSE;
- BOOL is_linden = FALSE;
- is_muted = LLMuteList::getInstance()->isMuted(
- from_id,
- from_name,
- LLMute::flagTextChat)
- || LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagTextChat);
- is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT &&
- LLMuteList::getInstance()->isLinden(from_name);
-
- BOOL is_audible = (CHAT_AUDIBLE_FULLY == chat.mAudible);
- chatter = gObjectList.findObject(from_id);
- if (chatter)
- {
- chat.mPosAgent = chatter->getPositionAgent();
-
- // Make swirly things only for talking objects. (not script debug messages, though)
- if (chat.mSourceType == CHAT_SOURCE_OBJECT
- && chat.mChatType != CHAT_TYPE_DEBUG_MSG)
- {
- LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent());
- psc->setSourceObject(chatter);
- psc->setColor(color);
- //We set the particles to be owned by the object's owner,
- //just in case they should be muted by the mute list
- psc->setOwnerUUID(owner_id);
- LLViewerPartSim::getInstance()->addPartSource(psc);
- }
-
- // record last audible utterance
- if (is_audible
- && (is_linden || (!is_muted && !is_busy)))
- {
- if (chat.mChatType != CHAT_TYPE_START
- && chat.mChatType != CHAT_TYPE_STOP)
- {
- gAgent.heardChat(chat.mFromID);
- }
- }
-
- is_owned_by_me = chatter->permYouOwner();
- }
-
- if (is_audible)
- {
- BOOL visible_in_chat_bubble = FALSE;
- std::string verb;
-
- color.setVec(1.f,1.f,1.f,1.f);
- msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg);
-
- BOOL ircstyle = FALSE;
-
- // Look for IRC-style emotes here so chatbubbles work
- 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;
- }
-
- // Look for the start of typing so we can put "..." in the bubbles.
- if (CHAT_TYPE_START == chat.mChatType)
- {
- LLLocalSpeakerMgr::getInstance()->setSpeakerTyping(from_id, TRUE);
-
- // Might not have the avatar constructed yet, eg on login.
- if (chatter && chatter->isAvatar())
- {
- ((LLVOAvatar*)chatter)->startTyping();
- }
- return;
- }
- else if (CHAT_TYPE_STOP == chat.mChatType)
- {
- LLLocalSpeakerMgr::getInstance()->setSpeakerTyping(from_id, FALSE);
-
- // Might not have the avatar constructed yet, eg on login.
- if (chatter && chatter->isAvatar())
- {
- ((LLVOAvatar*)chatter)->stopTyping();
- }
- return;
- }
-
- // We have a real utterance now, so can stop showing "..." and proceed.
- if (chatter && chatter->isAvatar())
- {
- LLLocalSpeakerMgr::getInstance()->setSpeakerTyping(from_id, FALSE);
- ((LLVOAvatar*)chatter)->stopTyping();
-
- if (!is_muted && !is_busy)
- {
- visible_in_chat_bubble = gSavedSettings.getBOOL("UseChatBubbles");
- ((LLVOAvatar*)chatter)->addChat(chat);
- }
- }
-
- // Look for IRC-style emotes
- if (ircstyle)
- {
- // set CHAT_STYLE_IRC to avoid adding Avatar Name as author of message. See EXT-656
- chat.mChatStyle = CHAT_STYLE_IRC;
-
- // Do nothing, ircstyle is fixed above for chat bubbles
- }
- else
- {
- switch(chat.mChatType)
- {
- case CHAT_TYPE_WHISPER:
- verb = "(" + LLTrans::getString("whisper") + ")";
- break;
- case CHAT_TYPE_DEBUG_MSG:
- case CHAT_TYPE_OWNER:
- case CHAT_TYPE_NORMAL:
- verb = "";
- break;
- case CHAT_TYPE_SHOUT:
- verb = "(" + LLTrans::getString("shout") + ")";
- break;
- case CHAT_TYPE_START:
- case CHAT_TYPE_STOP:
- LL_WARNS("Messaging") << "Got chat type start/stop in main chat processing." << LL_ENDL;
- break;
- default:
- LL_WARNS("Messaging") << "Unknown type " << chat.mChatType << " in chat!" << LL_ENDL;
- verb = "";
- break;
- }
-
-
- chat.mText = "";
- chat.mText += verb;
- chat.mText += mesg;
- }
-
- if (chatter)
- {
- chat.mPosAgent = chatter->getPositionAgent();
- }
-
- // truth table:
- // LINDEN BUSY MUTED OWNED_BY_YOU TASK DISPLAY STORE IN HISTORY
- // F F F F * Yes Yes
- // F F F T * Yes Yes
- // F F T F * No No
- // F F T T * No No
- // F T F F * No Yes
- // F T F T * Yes Yes
- // F T T F * No No
- // F T T T * No No
- // T * * * F Yes Yes
-
- chat.mMuted = is_muted && !is_linden;
-
- if (!visible_in_chat_bubble
- && (is_linden || !is_busy || is_owned_by_me))
- {
- // show on screen and add to history
- LLNotificationsUI::LLNotificationManager::instance().onChat(
- chat, LLNotificationsUI::NT_NEARBYCHAT);
-
- // adding temporarily so that communications window chat bar
- // works until the new chat window is ready
- chat.mText = from_name + ": " + chat.mText;
- LLFloaterChat::addChat(chat, FALSE, FALSE);
- }
- else
- {
- LLNotificationsUI::LLNotificationManager::instance().onChat(
- chat, LLNotificationsUI::NT_NEARBYCHAT);
- // adding temporarily
- LLFloaterChat::addChatHistory(chat);
- }
- }
-}
-
-
-// Simulator we're on is informing the viewer that the agent
-// is starting to teleport (perhaps to another sim, perhaps to the
-// same sim). If we initiated the teleport process by sending some kind
-// of TeleportRequest, then this info is redundant, but if the sim
-// initiated the teleport (via a script call, being killed, etc.)
-// then this info is news to us.
-void process_teleport_start(LLMessageSystem *msg, void**)
-{
- U32 teleport_flags = 0x0;
- msg->getU32("Info", "TeleportFlags", teleport_flags);
-
- if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL)
- {
- gViewerWindow->setProgressCancelButtonVisible(FALSE);
- }
- else
- {
- gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Cancel"));
- }
-
- // Freeze the UI and show progress bar
- // Note: could add data here to differentiate between normal teleport and death.
-
- if( gAgent.getTeleportState() == LLAgent::TELEPORT_NONE )
- {
- gTeleportDisplay = TRUE;
- gAgent.setTeleportState( LLAgent::TELEPORT_START );
- make_ui_sound("UISndTeleportOut");
-
- // Don't call LLFirstUse::useTeleport here because this could be
- // due to being killed, which would send you home, not to a Telehub
- }
-}
-
-void process_teleport_progress(LLMessageSystem* msg, void**)
-{
- LLUUID agent_id;
- msg->getUUID("AgentData", "AgentID", agent_id);
- if((gAgent.getID() != agent_id)
- || (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE))
- {
- LL_WARNS("Messaging") << "Unexpected teleport progress message." << LL_ENDL;
- return;
- }
- U32 teleport_flags = 0x0;
- msg->getU32("Info", "TeleportFlags", teleport_flags);
- if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL)
- {
- gViewerWindow->setProgressCancelButtonVisible(FALSE);
- }
- else
- {
- gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Cancel"));
- }
- std::string buffer;
- msg->getString("Info", "Message", buffer);
- LL_DEBUGS("Messaging") << "teleport progress: " << buffer << LL_ENDL;
-
- //Sorta hacky...default to using simulator raw messages
- //if we don't find the coresponding mapping in our progress mappings
- std::string message = buffer;
-
- if (LLAgent::sTeleportProgressMessages.find(buffer) !=
- LLAgent::sTeleportProgressMessages.end() )
- {
- message = LLAgent::sTeleportProgressMessages[buffer];
- }
-
- gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages[message]);
-}
-
-class LLFetchInWelcomeArea : public LLInventoryFetchDescendentsObserver
-{
-public:
- LLFetchInWelcomeArea() {}
- virtual void done()
- {
- LLIsType is_landmark(LLAssetType::AT_LANDMARK);
- LLIsType is_card(LLAssetType::AT_CALLINGCARD);
-
- LLInventoryModel::cat_array_t card_cats;
- LLInventoryModel::item_array_t card_items;
- LLInventoryModel::cat_array_t land_cats;
- LLInventoryModel::item_array_t land_items;
-
- folder_ref_t::iterator it = mCompleteFolders.begin();
- folder_ref_t::iterator end = mCompleteFolders.end();
- for(; it != end; ++it)
- {
- gInventory.collectDescendentsIf(
- (*it),
- land_cats,
- land_items,
- LLInventoryModel::EXCLUDE_TRASH,
- is_landmark);
- gInventory.collectDescendentsIf(
- (*it),
- card_cats,
- card_items,
- LLInventoryModel::EXCLUDE_TRASH,
- is_card);
- }
- LLSD args;
- if ( land_items.count() > 0 )
- { // Show notification that they can now teleport to landmarks. Use a random landmark from the inventory
- S32 random_land = ll_rand( land_items.count() - 1 );
- args["NAME"] = land_items[random_land]->getName();
- LLNotifications::instance().add("TeleportToLandmark",args);
- }
- if ( card_items.count() > 0 )
- { // Show notification that they can now contact people. Use a random calling card from the inventory
- S32 random_card = ll_rand( card_items.count() - 1 );
- args["NAME"] = card_items[random_card]->getName();
- LLNotifications::instance().add("TeleportToPerson",args);
- }
-
- gInventory.removeObserver(this);
- delete this;
- }
-};
-
-
-
-class LLPostTeleportNotifiers : public LLEventTimer
-{
-public:
- LLPostTeleportNotifiers();
- virtual ~LLPostTeleportNotifiers();
-
- //function to be called at the supplied frequency
- virtual BOOL tick();
-};
-
-LLPostTeleportNotifiers::LLPostTeleportNotifiers() : LLEventTimer( 2.0 )
-{
-};
-
-LLPostTeleportNotifiers::~LLPostTeleportNotifiers()
-{
-}
-
-BOOL LLPostTeleportNotifiers::tick()
-{
- BOOL all_done = FALSE;
- if ( gAgent.getTeleportState() == LLAgent::TELEPORT_NONE )
- {
- // get callingcards and landmarks available to the user arriving.
- LLInventoryFetchDescendentsObserver::folder_ref_t folders;
- LLUUID folder_id;
- folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
- if(folder_id.notNull())
- folders.push_back(folder_id);
- folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
- if(folder_id.notNull())
- folders.push_back(folder_id);
- if(!folders.empty())
- {
- LLFetchInWelcomeArea* fetcher = new LLFetchInWelcomeArea;
- fetcher->fetchDescendents(folders);
- if(fetcher->isEverythingComplete())
- {
- fetcher->done();
- }
- else
- {
- gInventory.addObserver(fetcher);
- }
- }
- all_done = TRUE;
- }
-
- return all_done;
-}
-
-
-
-// Teleport notification from the simulator
-// We're going to pretend to be a new agent
-void process_teleport_finish(LLMessageSystem* msg, void**)
-{
- LL_DEBUGS("Messaging") << "Got teleport location message" << LL_ENDL;
- LLUUID agent_id;
- msg->getUUIDFast(_PREHASH_Info, _PREHASH_AgentID, agent_id);
- if (agent_id != gAgent.getID())
- {
- LL_WARNS("Messaging") << "Got teleport notification for wrong agent!" << LL_ENDL;
- return;
- }
-
- // Do teleport effect for where you're leaving
- // VEFFECT: TeleportStart
- LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
- effectp->setPositionGlobal(gAgent.getPositionGlobal());
- effectp->setColor(LLColor4U(gAgent.getEffectColor()));
- LLHUDManager::getInstance()->sendEffects();
-
- U32 location_id;
- U32 sim_ip;
- U16 sim_port;
- LLVector3 pos, look_at;
- U64 region_handle;
- msg->getU32Fast(_PREHASH_Info, _PREHASH_LocationID, location_id);
- msg->getIPAddrFast(_PREHASH_Info, _PREHASH_SimIP, sim_ip);
- msg->getIPPortFast(_PREHASH_Info, _PREHASH_SimPort, sim_port);
- //msg->getVector3Fast(_PREHASH_Info, _PREHASH_Position, pos);
- //msg->getVector3Fast(_PREHASH_Info, _PREHASH_LookAt, look_at);
- msg->getU64Fast(_PREHASH_Info, _PREHASH_RegionHandle, region_handle);
- U32 teleport_flags;
- msg->getU32Fast(_PREHASH_Info, _PREHASH_TeleportFlags, teleport_flags);
-
-
- std::string seedCap;
- msg->getStringFast(_PREHASH_Info, _PREHASH_SeedCapability, seedCap);
-
- // update home location if we are teleporting out of prelude - specific to teleporting to welcome area
- if((teleport_flags & TELEPORT_FLAGS_SET_HOME_TO_TARGET)
- && (!gAgent.isGodlike()))
- {
- gAgent.setHomePosRegion(region_handle, pos);
-
- // Create a timer that will send notices when teleporting is all finished. Since this is
- // based on the LLEventTimer class, it will be managed by that class and not orphaned or leaked.
- new LLPostTeleportNotifiers();
- }
-
- LLHost sim_host(sim_ip, sim_port);
-
- // Viewer trusts the simulator.
- gMessageSystem->enableCircuit(sim_host, TRUE);
- LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host);
-
-/*
- // send camera update to new region
- gAgent.updateCamera();
-
- // likewise make sure the camera is behind the avatar
- gAgent.resetView(TRUE);
- LLVector3 shift_vector = regionp->getPosRegionFromGlobal(gAgent.getRegion()->getOriginGlobal());
- gAgent.setRegion(regionp);
- gObjectList.shiftObjects(shift_vector);
-
- if (gAgent.getAvatarObject())
- {
- gAgent.getAvatarObject()->clearChatText();
- gAgent.slamLookAt(look_at);
- }
- gAgent.setPositionAgent(pos);
- gAssetStorage->setUpstream(sim);
- gCacheName->setUpstream(sim);
-*/
-
- // now, use the circuit info to tell simulator about us!
- LL_INFOS("Messaging") << "process_teleport_finish() Enabling "
- << sim_host << " with code " << msg->mOurCircuitCode << LL_ENDL;
- msg->newMessageFast(_PREHASH_UseCircuitCode);
- msg->nextBlockFast(_PREHASH_CircuitCode);
- msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addUUIDFast(_PREHASH_ID, gAgent.getID());
- msg->sendReliable(sim_host);
-
- send_complete_agent_movement(sim_host);
- gAgent.setTeleportState( LLAgent::TELEPORT_MOVING );
- gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["contacting"]);
-
- regionp->setSeedCapability(seedCap);
-
- // Don't send camera updates to the new region until we're
- // actually there...
-
-
- // Now do teleport effect for where you're going.
- // VEFFECT: TeleportEnd
- effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
- effectp->setPositionGlobal(gAgent.getPositionGlobal());
-
- effectp->setColor(LLColor4U(gAgent.getEffectColor()));
- LLHUDManager::getInstance()->sendEffects();
-
-// gTeleportDisplay = TRUE;
-// gTeleportDisplayTimer.reset();
-// gViewerWindow->setShowProgress(TRUE);
-}
-
-// stuff we have to do every time we get an AvatarInitComplete from a sim
-/*
-void process_avatar_init_complete(LLMessageSystem* msg, void**)
-{
- LLVector3 agent_pos;
- msg->getVector3Fast(_PREHASH_AvatarData, _PREHASH_Position, agent_pos);
- agent_movement_complete(msg->getSender(), agent_pos);
-}
-*/
-
-void process_agent_movement_complete(LLMessageSystem* msg, void**)
-{
- gAgentMovementCompleted = true;
-
- LLUUID agent_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- LLUUID session_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id);
- if((gAgent.getID() != agent_id) || (gAgent.getSessionID() != session_id))
- {
- LL_WARNS("Messaging") << "Incorrect id in process_agent_movement_complete()"
- << LL_ENDL;
- return;
- }
-
- LL_DEBUGS("Messaging") << "process_agent_movement_complete()" << LL_ENDL;
-
- // *TODO: check timestamp to make sure the movement compleation
- // makes sense.
- LLVector3 agent_pos;
- msg->getVector3Fast(_PREHASH_Data, _PREHASH_Position, agent_pos);
- LLVector3 look_at;
- msg->getVector3Fast(_PREHASH_Data, _PREHASH_LookAt, look_at);
- U64 region_handle;
- msg->getU64Fast(_PREHASH_Data, _PREHASH_RegionHandle, region_handle);
-
- std::string version_channel;
- msg->getString("SimData", "ChannelVersion", version_channel);
-
- LLVOAvatar* avatarp = gAgent.getAvatarObject();
- if (!avatarp)
- {
- // Could happen if you were immediately god-teleported away on login,
- // maybe other cases. Continue, but warn.
- LL_WARNS("Messaging") << "agent_movement_complete() with NULL avatarp." << LL_ENDL;
- }
-
- F32 x, y;
- from_region_handle(region_handle, &x, &y);
- LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle);
- if (!regionp)
- {
- if (gAgent.getRegion())
- {
- LL_WARNS("Messaging") << "current region " << gAgent.getRegion()->getOriginGlobal() << LL_ENDL;
- }
-
- LL_WARNS("Messaging") << "Agent being sent to invalid home region: "
- << x << ":" << y
- << " current pos " << gAgent.getPositionGlobal()
- << LL_ENDL;
- LLAppViewer::instance()->forceDisconnect("You were sent to an invalid region.");
- return;
-
- }
-
- LL_INFOS("Messaging") << "Changing home region to " << x << ":" << y << LL_ENDL;
-
- // set our upstream host the new simulator and shuffle things as
- // appropriate.
- LLVector3 shift_vector = regionp->getPosRegionFromGlobal(
- gAgent.getRegion()->getOriginGlobal());
- gAgent.setRegion(regionp);
- gObjectList.shiftObjects(shift_vector);
- gAssetStorage->setUpstream(msg->getSender());
- gCacheName->setUpstream(msg->getSender());
- gViewerThrottle.sendToSim();
- gViewerWindow->sendShapeToSim();
-
- bool is_teleport = gAgent.getTeleportState() == LLAgent::TELEPORT_MOVING;
-
- if( is_teleport )
- {
- // Force the camera back onto the agent, don't animate.
- gAgent.setFocusOnAvatar(TRUE, FALSE);
- gAgent.slamLookAt(look_at);
- gAgent.updateCamera();
-
- gAgent.setTeleportState( LLAgent::TELEPORT_START_ARRIVAL );
-
- // set the appearance on teleport since the new sim does not
- // know what you look like.
- gAgent.sendAgentSetAppearance();
-
- if (avatarp)
- {
- // Chat the "back" SLURL. (DEV-4907)
- LLChat chat("Teleport completed from " + gAgent.getTeleportSourceSLURL());
- chat.mSourceType = CHAT_SOURCE_SYSTEM;
- LLFloaterChat::addChatHistory(chat);
-
- // Set the new position
- avatarp->setPositionAgent(agent_pos);
- avatarp->clearChat();
- avatarp->slamPosition();
- }
- }
- else
- {
- // This is likely just the initial logging in phase.
- gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
- }
-
- if ( LLTracker::isTracking(NULL) )
- {
- // Check distance to beacon, if < 5m, remove beacon
- LLVector3d beacon_pos = LLTracker::getTrackedPositionGlobal();
- LLVector3 beacon_dir(agent_pos.mV[VX] - (F32)fmod(beacon_pos.mdV[VX], 256.0), agent_pos.mV[VY] - (F32)fmod(beacon_pos.mdV[VY], 256.0), 0);
- if (beacon_dir.magVecSquared() < 25.f)
- {
- LLTracker::stopTracking(NULL);
- }
- else if ( is_teleport )
- {
- //look at the beacon
- LLVector3 global_agent_pos = agent_pos;
- global_agent_pos[0] += x;
- global_agent_pos[1] += y;
- look_at = (LLVector3)beacon_pos - global_agent_pos;
- look_at.normVec();
- gAgent.slamLookAt(look_at);
- }
- }
-
- // TODO: Put back a check for flying status! DK 12/19/05
- // Sim tells us whether the new position is off the ground
- /*
- if (teleport_flags & TELEPORT_FLAGS_IS_FLYING)
- {
- gAgent.setFlying(TRUE);
- }
- else
- {
- gAgent.setFlying(FALSE);
- }
- */
-
- send_agent_update(TRUE, TRUE);
-
- if (gAgent.getRegion()->getBlockFly())
- {
- gAgent.setFlying(gAgent.canFly());
- }
-
- // force simulator to recognize busy state
- if (gAgent.getBusy())
- {
- gAgent.setBusy();
- }
- else
- {
- gAgent.clearBusy();
- }
-
- if (avatarp)
- {
- avatarp->mFootPlane.clearVec();
- }
-
- // send walk-vs-run status
- gAgent.sendWalkRun(gAgent.getRunning() || gAgent.getAlwaysRun());
-
- // If the server version has changed, display an info box and offer
- // to display the release notes, unless this is the initial log in.
- if (gLastVersionChannel == version_channel)
- {
- return;
- }
-
- if (!gLastVersionChannel.empty())
- {
- LLSD payload;
- payload["message"] = version_channel;
- LLNotifications::instance().add("ServerVersionChanged", LLSD(), payload, server_version_changed_callback);
- }
-
- gLastVersionChannel = version_channel;
-}
-
-bool server_version_changed_callback(const LLSD& notification, const LLSD& response)
-{
- if(notification["payload"]["message"].asString() =="")
- return false;
- std::string url ="http://wiki.secondlife.com/wiki/Release_Notes/";
- //parse the msg string
- std::string server_version = notification["payload"]["message"].asString();
- std::vector<std::string> s_vect;
- boost::algorithm::split(s_vect, server_version, isspace);
- for(U32 i = 0; i < s_vect.size(); i++)
- {
- if (i != (s_vect.size() - 1))
- {
- if(i != (s_vect.size() - 2))
- {
- url += s_vect[i] + "_";
- }
- else
- {
- url += s_vect[i] + "/";
- }
- }
- else
- {
- url += s_vect[i].substr(0,4);
- }
- }
-
- LLWeb::loadURL(url);
- return false;
-}
-
-
-void process_crossed_region(LLMessageSystem* msg, void**)
-{
- LLUUID agent_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- LLUUID session_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id);
- if((gAgent.getID() != agent_id) || (gAgent.getSessionID() != session_id))
- {
- LL_WARNS("Messaging") << "Incorrect id in process_crossed_region()"
- << LL_ENDL;
- return;
- }
- LL_INFOS("Messaging") << "process_crossed_region()" << LL_ENDL;
-
- U32 sim_ip;
- msg->getIPAddrFast(_PREHASH_RegionData, _PREHASH_SimIP, sim_ip);
- U16 sim_port;
- msg->getIPPortFast(_PREHASH_RegionData, _PREHASH_SimPort, sim_port);
- LLHost sim_host(sim_ip, sim_port);
- U64 region_handle;
- msg->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
-
- std::string seedCap;
- msg->getStringFast(_PREHASH_RegionData, _PREHASH_SeedCapability, seedCap);
-
- send_complete_agent_movement(sim_host);
-
- LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host);
- regionp->setSeedCapability(seedCap);
-}
-
-
-
-// Sends avatar and camera information to simulator.
-// Sent roughly once per frame, or 20 times per second, whichever is less often
-
-const F32 THRESHOLD_HEAD_ROT_QDOT = 0.9997f; // ~= 2.5 degrees -- if its less than this we need to update head_rot
-const F32 MAX_HEAD_ROT_QDOT = 0.99999f; // ~= 0.5 degrees -- if its greater than this then no need to update head_rot
- // between these values we delay the updates (but no more than one second)
-
-
-void send_agent_update(BOOL force_send, BOOL send_reliable)
-{
- if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE)
- {
- // We don't care if they want to send an agent update, they're not allowed to until the simulator
- // that's the target is ready to receive them (after avatar_init_complete is received)
- return;
- }
-
- // We have already requested to log out. Don't send agent updates.
- if(LLAppViewer::instance()->logoutRequestSent())
- {
- return;
- }
-
- // no region to send update to
- if(gAgent.getRegion() == NULL)
- {
- return;
- }
-
- const F32 TRANSLATE_THRESHOLD = 0.01f;
-
- // NOTA BENE: This is (intentionally?) using the small angle sine approximation to test for rotation
- // Plus, there is an extra 0.5 in the mix since the perpendicular between last_camera_at and getAtAxis() bisects cam_rot_change
- // Thus, we're actually testing against 0.2 degrees
- const F32 ROTATION_THRESHOLD = 0.1f * 2.f*F_PI/360.f; // Rotation thresh 0.2 deg, see note above
-
- const U8 DUP_MSGS = 1; // HACK! number of times to repeat data on motionless agent
-
- // Store data on last sent update so that if no changes, no send
- static LLVector3 last_camera_pos_agent,
- last_camera_at,
- last_camera_left,
- last_camera_up;
-
- static LLVector3 cam_center_chg,
- cam_rot_chg;
-
- static LLQuaternion last_head_rot;
- static U32 last_control_flags = 0;
- static U8 last_render_state;
- static U8 duplicate_count = 0;
- static F32 head_rot_chg = 1.0;
- static U8 last_flags;
-
- LLMessageSystem *msg = gMessageSystem;
- LLVector3 camera_pos_agent; // local to avatar's region
- U8 render_state;
-
- LLQuaternion body_rotation = gAgent.getFrameAgent().getQuaternion();
- LLQuaternion head_rotation = gAgent.getHeadRotation();
-
- camera_pos_agent = gAgent.getCameraPositionAgent();
-
- render_state = gAgent.getRenderState();
-
- U32 control_flag_change = 0;
- U8 flag_change = 0;
-
- cam_center_chg = last_camera_pos_agent - camera_pos_agent;
- cam_rot_chg = last_camera_at - LLViewerCamera::getInstance()->getAtAxis();
-
- // If a modifier key is held down, turn off
- // LBUTTON and ML_LBUTTON so that using the camera (alt-key) doesn't
- // trigger a control event.
- U32 control_flags = gAgent.getControlFlags();
- MASK key_mask = gKeyboard->currentMask(TRUE);
- if (key_mask & MASK_ALT || key_mask & MASK_CONTROL)
- {
- control_flags &= ~( AGENT_CONTROL_LBUTTON_DOWN |
- AGENT_CONTROL_ML_LBUTTON_DOWN );
- control_flags |= AGENT_CONTROL_LBUTTON_UP |
- AGENT_CONTROL_ML_LBUTTON_UP ;
- }
-
- control_flag_change = last_control_flags ^ control_flags;
-
- U8 flags = AU_FLAGS_NONE;
- if (gAgent.isGroupTitleHidden())
- {
- flags |= AU_FLAGS_HIDETITLE;
- }
- if (gAgent.getAutoPilot())
- {
- flags |= AU_FLAGS_CLIENT_AUTOPILOT;
- }
-
- flag_change = last_flags ^ flags;
-
- head_rot_chg = dot(last_head_rot, head_rotation);
-
- if (force_send ||
- (cam_center_chg.magVec() > TRANSLATE_THRESHOLD) ||
- (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT) ||
- (last_render_state != render_state) ||
- (cam_rot_chg.magVec() > ROTATION_THRESHOLD) ||
- control_flag_change != 0 ||
- flag_change != 0)
- {
-/*
- if (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT)
- {
- //LL_INFOS("Messaging") << "head rot " << head_rotation << LL_ENDL;
- LL_INFOS("Messaging") << "head_rot_chg = " << head_rot_chg << LL_ENDL;
- }
- if (cam_rot_chg.magVec() > ROTATION_THRESHOLD)
- {
- LL_INFOS("Messaging") << "cam rot " << cam_rot_chg.magVec() << LL_ENDL;
- }
- if (cam_center_chg.magVec() > TRANSLATE_THRESHOLD)
- {
- LL_INFOS("Messaging") << "cam center " << cam_center_chg.magVec() << LL_ENDL;
- }
-// if (drag_delta_chg.magVec() > TRANSLATE_THRESHOLD)
-// {
-// LL_INFOS("Messaging") << "drag delta " << drag_delta_chg.magVec() << LL_ENDL;
-// }
- if (control_flag_change)
- {
- LL_INFOS("Messaging") << "dcf = " << control_flag_change << LL_ENDL;
- }
-*/
-
- duplicate_count = 0;
- }
- else
- {
- duplicate_count++;
-
- if (head_rot_chg < MAX_HEAD_ROT_QDOT && duplicate_count < AGENT_UPDATES_PER_SECOND)
- {
- // The head_rotation is sent for updating things like attached guns.
- // We only trigger a new update when head_rotation deviates beyond
- // some threshold from the last update, however this can break fine
- // adjustments when trying to aim an attached gun, so what we do here
- // (where we would normally skip sending an update when nothing has changed)
- // is gradually reduce the threshold to allow a better update to
- // eventually get sent... should update to within 0.5 degrees in less
- // than a second.
- if (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT + (MAX_HEAD_ROT_QDOT - THRESHOLD_HEAD_ROT_QDOT) * duplicate_count / AGENT_UPDATES_PER_SECOND)
- {
- duplicate_count = 0;
- }
- else
- {
- return;
- }
- }
- else
- {
- return;
- }
- }
-
- if (duplicate_count < DUP_MSGS && !gDisconnected)
- {
- // Build the message
- msg->newMessageFast(_PREHASH_AgentUpdate);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addQuatFast(_PREHASH_BodyRotation, body_rotation);
- msg->addQuatFast(_PREHASH_HeadRotation, head_rotation);
- msg->addU8Fast(_PREHASH_State, render_state);
- msg->addU8Fast(_PREHASH_Flags, flags);
-
-// if (camera_pos_agent.mV[VY] > 255.f)
-// {
-// LL_INFOS("Messaging") << "Sending camera center " << camera_pos_agent << LL_ENDL;
-// }
-
- msg->addVector3Fast(_PREHASH_CameraCenter, camera_pos_agent);
- msg->addVector3Fast(_PREHASH_CameraAtAxis, LLViewerCamera::getInstance()->getAtAxis());
- msg->addVector3Fast(_PREHASH_CameraLeftAxis, LLViewerCamera::getInstance()->getLeftAxis());
- msg->addVector3Fast(_PREHASH_CameraUpAxis, LLViewerCamera::getInstance()->getUpAxis());
- msg->addF32Fast(_PREHASH_Far, gAgent.mDrawDistance);
-
- msg->addU32Fast(_PREHASH_ControlFlags, control_flags);
-
- if (gDebugClicks)
- {
- if (control_flags & AGENT_CONTROL_LBUTTON_DOWN)
- {
- LL_INFOS("Messaging") << "AgentUpdate left button down" << LL_ENDL;
- }
-
- if (control_flags & AGENT_CONTROL_LBUTTON_UP)
- {
- LL_INFOS("Messaging") << "AgentUpdate left button up" << LL_ENDL;
- }
- }
-
- gAgent.enableControlFlagReset();
-
- if (!send_reliable)
- {
- gAgent.sendMessage();
- }
- else
- {
- gAgent.sendReliableMessage();
- }
-
-// LL_DEBUGS("Messaging") << "agent " << avatar_pos_agent << " cam " << camera_pos_agent << LL_ENDL;
-
- // Copy the old data
- last_head_rot = head_rotation;
- last_render_state = render_state;
- last_camera_pos_agent = camera_pos_agent;
- last_camera_at = LLViewerCamera::getInstance()->getAtAxis();
- last_camera_left = LLViewerCamera::getInstance()->getLeftAxis();
- last_camera_up = LLViewerCamera::getInstance()->getUpAxis();
- last_control_flags = control_flags;
- last_flags = flags;
- }
-}
-
-
-
-// *TODO: Remove this dependency, or figure out a better way to handle
-// this hack.
-extern U32 gObjectBits;
-
-void process_object_update(LLMessageSystem *mesgsys, void **user_data)
-{
- LLMemType mt(LLMemType::MTYPE_OBJECT);
- // Update the data counters
- if (mesgsys->getReceiveCompressedSize())
- {
- gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
- }
- else
- {
- gObjectBits += mesgsys->getReceiveSize() * 8;
- }
-
- // Update the object...
- gObjectList.processObjectUpdate(mesgsys, user_data, OUT_FULL);
-}
-
-void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data)
-{
- LLMemType mt(LLMemType::MTYPE_OBJECT);
- // Update the data counters
- if (mesgsys->getReceiveCompressedSize())
- {
- gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
- }
- else
- {
- gObjectBits += mesgsys->getReceiveSize() * 8;
- }
-
- // Update the object...
- gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_FULL_COMPRESSED);
-}
-
-void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
-{
- LLMemType mt(LLMemType::MTYPE_OBJECT);
- // Update the data counters
- if (mesgsys->getReceiveCompressedSize())
- {
- gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
- }
- else
- {
- gObjectBits += mesgsys->getReceiveSize() * 8;
- }
-
- // Update the object...
- gObjectList.processCachedObjectUpdate(mesgsys, user_data, OUT_FULL_CACHED);
-}
-
-
-void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_data)
-{
- LLMemType mt(LLMemType::MTYPE_OBJECT);
- if (mesgsys->getReceiveCompressedSize())
- {
- gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
- }
- else
- {
- gObjectBits += mesgsys->getReceiveSize() * 8;
- }
-
- gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_TERSE_IMPROVED);
-}
-
-static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Objects");
-
-
-void process_kill_object(LLMessageSystem *mesgsys, void **user_data)
-{
- LLFastTimer t(FTM_PROCESS_OBJECTS);
-
- LLUUID id;
- U32 local_id;
- S32 i;
- S32 num_objects;
-
- num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData);
-
- for (i = 0; i < num_objects; i++)
- {
- mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
-
- LLViewerObjectList::getUUIDFromLocal(id,
- local_id,
- gMessageSystem->getSenderIP(),
- gMessageSystem->getSenderPort());
- if (id == LLUUID::null)
- {
- LL_DEBUGS("Messaging") << "Unknown kill for local " << local_id << LL_ENDL;
- gObjectList.mNumUnknownKills++;
- continue;
- }
- else
- {
- LL_DEBUGS("Messaging") << "Kill message for local " << local_id << LL_ENDL;
- }
-
- LLSelectMgr::getInstance()->removeObjectFromSelections(id);
-
- // ...don't kill the avatar
- if (!(id == gAgentID))
- {
- LLViewerObject *objectp = gObjectList.findObject(id);
- if (objectp)
- {
- // Display green bubble on kill
- if ( gShowObjectUpdates )
- {
- LLViewerObject* newobject;
- newobject = gObjectList.createObjectViewer(LL_PCODE_LEGACY_TEXT_BUBBLE, objectp->getRegion());
-
- LLVOTextBubble* bubble = (LLVOTextBubble*) newobject;
-
- bubble->mColor.setVec(0.f, 1.f, 0.f, 1.f);
- bubble->setScale( 2.0f * bubble->getScale() );
- bubble->setPositionGlobal(objectp->getPositionGlobal());
- gPipeline.addObject(bubble);
- }
-
- // Do the kill
- gObjectList.killObject(objectp);
- }
- else
- {
- LL_WARNS("Messaging") << "Object in UUID lookup, but not on object list in kill!" << LL_ENDL;
- gObjectList.mNumUnknownKills++;
- }
- }
- }
-}
-
-void process_time_synch(LLMessageSystem *mesgsys, void **user_data)
-{
- LLVector3 sun_direction;
- LLVector3 sun_ang_velocity;
- F32 phase;
- U64 space_time_usec;
-
- U32 seconds_per_day;
- U32 seconds_per_year;
-
- // "SimulatorViewerTimeMessage"
- mesgsys->getU64Fast(_PREHASH_TimeInfo, _PREHASH_UsecSinceStart, space_time_usec);
- mesgsys->getU32Fast(_PREHASH_TimeInfo, _PREHASH_SecPerDay, seconds_per_day);
- mesgsys->getU32Fast(_PREHASH_TimeInfo, _PREHASH_SecPerYear, seconds_per_year);
-
- // This should eventually be moved to an "UpdateHeavenlyBodies" message
- mesgsys->getF32Fast(_PREHASH_TimeInfo, _PREHASH_SunPhase, phase);
- mesgsys->getVector3Fast(_PREHASH_TimeInfo, _PREHASH_SunDirection, sun_direction);
- mesgsys->getVector3Fast(_PREHASH_TimeInfo, _PREHASH_SunAngVelocity, sun_ang_velocity);
-
- LLWorld::getInstance()->setSpaceTimeUSec(space_time_usec);
-
- //LL_DEBUGS("Messaging") << "time_synch() - " << sun_direction << ", " << sun_ang_velocity
- // << ", " << phase << LL_ENDL;
-
- gSky.setSunPhase(phase);
- gSky.setSunTargetDirection(sun_direction, sun_ang_velocity);
- if (!gNoRender && !(gSavedSettings.getBOOL("SkyOverrideSimSunPosition") || gSky.getOverrideSun()))
- {
- gSky.setSunDirection(sun_direction, sun_ang_velocity);
- }
-}
-
-void process_sound_trigger(LLMessageSystem *msg, void **)
-{
- if (!gAudiop) return;
-
- U64 region_handle = 0;
- F32 gain = 0;
- LLUUID sound_id;
- LLUUID owner_id;
- LLUUID object_id;
- LLUUID parent_id;
- LLVector3 pos_local;
-
- msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_SoundID, sound_id);
- msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_OwnerID, owner_id);
- msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_ObjectID, object_id);
- msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_ParentID, parent_id);
- msg->getU64Fast(_PREHASH_SoundData, _PREHASH_Handle, region_handle);
- msg->getVector3Fast(_PREHASH_SoundData, _PREHASH_Position, pos_local);
- msg->getF32Fast(_PREHASH_SoundData, _PREHASH_Gain, gain);
-
- // adjust sound location to true global coords
- LLVector3d pos_global = from_region_handle(region_handle);
- pos_global.mdV[VX] += pos_local.mV[VX];
- pos_global.mdV[VY] += pos_local.mV[VY];
- pos_global.mdV[VZ] += pos_local.mV[VZ];
-
- // Don't play a trigger sound if you can't hear it due
- // to parcel "local audio only" settings.
- if (!LLViewerParcelMgr::getInstance()->canHearSound(pos_global)) return;
-
- // Don't play sounds triggered by someone you muted.
- if (LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagObjectSounds)) return;
-
- // Don't play sounds from an object you muted
- if (LLMuteList::getInstance()->isMuted(object_id)) return;
-
- // Don't play sounds from an object whose parent you muted
- if (parent_id.notNull()
- && LLMuteList::getInstance()->isMuted(parent_id))
- {
- return;
- }
-
- // Don't play sounds from a region with maturity above current agent maturity
- if( !gAgent.canAccessMaturityInRegion( region_handle ) )
- {
- return;
- }
-
- gAudiop->triggerSound(sound_id, owner_id, gain, LLAudioEngine::AUDIO_TYPE_SFX, pos_global);
-}
-
-void process_preload_sound(LLMessageSystem *msg, void **user_data)
-{
- if (!gAudiop)
- {
- return;
- }
-
- LLUUID sound_id;
- LLUUID object_id;
- LLUUID owner_id;
-
- msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_SoundID, sound_id);
- msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_ObjectID, object_id);
- msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_OwnerID, owner_id);
-
- LLViewerObject *objectp = gObjectList.findObject(object_id);
- if (!objectp) return;
-
- if (LLMuteList::getInstance()->isMuted(object_id)) return;
- if (LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagObjectSounds)) return;
-
- LLAudioSource *sourcep = objectp->getAudioSource(owner_id);
- if (!sourcep) return;
-
- LLAudioData *datap = gAudiop->getAudioData(sound_id);
-
- // Note that I don't actually do any loading of the
- // audio data into a buffer at this point, as it won't actually
- // help us out.
-
- // Don't play sounds from a region with maturity above current agent maturity
- LLVector3d pos_global = objectp->getPositionGlobal();
- if( !gAgent.canAccessMaturityAtGlobal( pos_global ) )
- {
- return;
- }
-
- // Add audioData starts a transfer internally.
- sourcep->addAudioData(datap, FALSE);
-}
-
-void process_attached_sound(LLMessageSystem *msg, void **user_data)
-{
- F32 gain = 0;
- LLUUID sound_id;
- LLUUID object_id;
- LLUUID owner_id;
- U8 flags;
-
- msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_SoundID, sound_id);
- msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_ObjectID, object_id);
- msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_OwnerID, owner_id);
- msg->getF32Fast(_PREHASH_DataBlock, _PREHASH_Gain, gain);
- msg->getU8Fast(_PREHASH_DataBlock, _PREHASH_Flags, flags);
-
- LLViewerObject *objectp = gObjectList.findObject(object_id);
- if (!objectp)
- {
- // we don't know about this object, just bail
- return;
- }
-
- if (LLMuteList::getInstance()->isMuted(object_id)) return;
-
- if (LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagObjectSounds)) return;
-
-
- // Don't play sounds from a region with maturity above current agent maturity
- LLVector3d pos = objectp->getPositionGlobal();
- if( !gAgent.canAccessMaturityAtGlobal(pos) )
- {
- return;
- }
-
- objectp->setAttachedSound(sound_id, owner_id, gain, flags);
-}
-
-
-void process_attached_sound_gain_change(LLMessageSystem *mesgsys, void **user_data)
-{
- F32 gain = 0;
- LLUUID object_guid;
- LLViewerObject *objectp = NULL;
-
- mesgsys->getUUIDFast(_PREHASH_DataBlock, _PREHASH_ObjectID, object_guid);
-
- if (!((objectp = gObjectList.findObject(object_guid))))
- {
- // we don't know about this object, just bail
- return;
- }
-
- mesgsys->getF32Fast(_PREHASH_DataBlock, _PREHASH_Gain, gain);
-
- objectp->adjustAudioGain(gain);
-}
-
-
-void process_health_message(LLMessageSystem *mesgsys, void **user_data)
-{
- F32 health;
-
- mesgsys->getF32Fast(_PREHASH_HealthData, _PREHASH_Health, health);
-
- if (gStatusBar)
- {
- gStatusBar->setHealth((S32)health);
- }
-}
-
-
-void process_sim_stats(LLMessageSystem *msg, void **user_data)
-{
- S32 count = msg->getNumberOfBlocks("Stat");
- for (S32 i = 0; i < count; ++i)
- {
- U32 stat_id;
- F32 stat_value;
- msg->getU32("Stat", "StatID", stat_id, i);
- msg->getF32("Stat", "StatValue", stat_value, i);
- switch (stat_id)
- {
- case LL_SIM_STAT_TIME_DILATION:
- LLViewerStats::getInstance()->mSimTimeDilation.addValue(stat_value);
- break;
- case LL_SIM_STAT_FPS:
- LLViewerStats::getInstance()->mSimFPS.addValue(stat_value);
- break;
- case LL_SIM_STAT_PHYSFPS:
- LLViewerStats::getInstance()->mSimPhysicsFPS.addValue(stat_value);
- break;
- case LL_SIM_STAT_AGENTUPS:
- LLViewerStats::getInstance()->mSimAgentUPS.addValue(stat_value);
- break;
- case LL_SIM_STAT_FRAMEMS:
- LLViewerStats::getInstance()->mSimFrameMsec.addValue(stat_value);
- break;
- case LL_SIM_STAT_NETMS:
- LLViewerStats::getInstance()->mSimNetMsec.addValue(stat_value);
- break;
- case LL_SIM_STAT_SIMOTHERMS:
- LLViewerStats::getInstance()->mSimSimOtherMsec.addValue(stat_value);
- break;
- case LL_SIM_STAT_SIMPHYSICSMS:
- LLViewerStats::getInstance()->mSimSimPhysicsMsec.addValue(stat_value);
- break;
- case LL_SIM_STAT_AGENTMS:
- LLViewerStats::getInstance()->mSimAgentMsec.addValue(stat_value);
- break;
- case LL_SIM_STAT_IMAGESMS:
- LLViewerStats::getInstance()->mSimImagesMsec.addValue(stat_value);
- break;
- case LL_SIM_STAT_SCRIPTMS:
- LLViewerStats::getInstance()->mSimScriptMsec.addValue(stat_value);
- break;
- case LL_SIM_STAT_NUMTASKS:
- LLViewerStats::getInstance()->mSimObjects.addValue(stat_value);
- break;
- case LL_SIM_STAT_NUMTASKSACTIVE:
- LLViewerStats::getInstance()->mSimActiveObjects.addValue(stat_value);
- break;
- case LL_SIM_STAT_NUMAGENTMAIN:
- LLViewerStats::getInstance()->mSimMainAgents.addValue(stat_value);
- break;
- case LL_SIM_STAT_NUMAGENTCHILD:
- LLViewerStats::getInstance()->mSimChildAgents.addValue(stat_value);
- break;
- case LL_SIM_STAT_NUMSCRIPTSACTIVE:
- LLViewerStats::getInstance()->mSimActiveScripts.addValue(stat_value);
- break;
- case LL_SIM_STAT_SCRIPT_EPS:
- LLViewerStats::getInstance()->mSimScriptEPS.addValue(stat_value);
- break;
- case LL_SIM_STAT_INPPS:
- LLViewerStats::getInstance()->mSimInPPS.addValue(stat_value);
- break;
- case LL_SIM_STAT_OUTPPS:
- LLViewerStats::getInstance()->mSimOutPPS.addValue(stat_value);
- break;
- case LL_SIM_STAT_PENDING_DOWNLOADS:
- LLViewerStats::getInstance()->mSimPendingDownloads.addValue(stat_value);
- break;
- case LL_SIM_STAT_PENDING_UPLOADS:
- LLViewerStats::getInstance()->mSimPendingUploads.addValue(stat_value);
- break;
- case LL_SIM_STAT_PENDING_LOCAL_UPLOADS:
- LLViewerStats::getInstance()->mSimPendingLocalUploads.addValue(stat_value);
- break;
- case LL_SIM_STAT_TOTAL_UNACKED_BYTES:
- LLViewerStats::getInstance()->mSimTotalUnackedBytes.addValue(stat_value / 1024.f);
- break;
- case LL_SIM_STAT_PHYSICS_PINNED_TASKS:
- LLViewerStats::getInstance()->mPhysicsPinnedTasks.addValue(stat_value);
- break;
- case LL_SIM_STAT_PHYSICS_LOD_TASKS:
- LLViewerStats::getInstance()->mPhysicsLODTasks.addValue(stat_value);
- break;
- case LL_SIM_STAT_SIMPHYSICSSTEPMS:
- LLViewerStats::getInstance()->mSimSimPhysicsStepMsec.addValue(stat_value);
- break;
- case LL_SIM_STAT_SIMPHYSICSSHAPEMS:
- LLViewerStats::getInstance()->mSimSimPhysicsShapeUpdateMsec.addValue(stat_value);
- break;
- case LL_SIM_STAT_SIMPHYSICSOTHERMS:
- LLViewerStats::getInstance()->mSimSimPhysicsOtherMsec.addValue(stat_value);
- break;
- case LL_SIM_STAT_SIMPHYSICSMEMORY:
- LLViewerStats::getInstance()->mPhysicsMemoryAllocated.addValue(stat_value);
- break;
- case LL_SIM_STAT_SIMSPARETIME:
- LLViewerStats::getInstance()->mSimSpareMsec.addValue(stat_value);
- break;
- case LL_SIM_STAT_SIMSLEEPTIME:
- LLViewerStats::getInstance()->mSimSleepMsec.addValue(stat_value);
- break;
- case LL_SIM_STAT_IOPUMPTIME:
- LLViewerStats::getInstance()->mSimPumpIOMsec.addValue(stat_value);
- break;
- default:
- // Used to be a commented out warning.
- LL_DEBUGS("Messaging") << "Unknown stat id" << stat_id << LL_ENDL;
- break;
- }
- }
-
- /*
- msg->getF32Fast(_PREHASH_Statistics, _PREHASH_PhysicsTimeDilation, time_dilation);
- LLViewerStats::getInstance()->mSimTDStat.addValue(time_dilation);
-
- // Process information
- // { CpuUsage F32 }
- // { SimMemTotal F32 }
- // { SimMemRSS F32 }
- // { ProcessUptime F32 }
- F32 cpu_usage;
- F32 sim_mem_total;
- F32 sim_mem_rss;
- F32 process_uptime;
- msg->getF32Fast(_PREHASH_Statistics, _PREHASH_CpuUsage, cpu_usage);
- msg->getF32Fast(_PREHASH_Statistics, _PREHASH_SimMemTotal, sim_mem_total);
- msg->getF32Fast(_PREHASH_Statistics, _PREHASH_SimMemRSS, sim_mem_rss);
- msg->getF32Fast(_PREHASH_Statistics, _PREHASH_ProcessUptime, process_uptime);
- LLViewerStats::getInstance()->mSimCPUUsageStat.addValue(cpu_usage);
- LLViewerStats::getInstance()->mSimMemTotalStat.addValue(sim_mem_total);
- LLViewerStats::getInstance()->mSimMemRSSStat.addValue(sim_mem_rss);
- */
-
- //
- // Various hacks that aren't statistics, but are being handled here.
- //
- U32 max_tasks_per_region;
- U32 region_flags;
- msg->getU32("Region", "ObjectCapacity", max_tasks_per_region);
- msg->getU32("Region", "RegionFlags", region_flags);
-
- LLViewerRegion* regionp = gAgent.getRegion();
- if (regionp)
- {
- BOOL was_flying = gAgent.getFlying();
- regionp->setRegionFlags(region_flags);
- regionp->setMaxTasks(max_tasks_per_region);
- // HACK: This makes agents drop from the sky if the region is
- // set to no fly while people are still in the sim.
- if (was_flying && regionp->getBlockFly())
- {
- gAgent.setFlying(gAgent.canFly());
- }
- }
-}
-
-
-
-void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
-{
- LLUUID animation_id;
- LLUUID uuid;
- S32 anim_sequence_id;
- LLVOAvatar *avatarp;
-
- mesgsys->getUUIDFast(_PREHASH_Sender, _PREHASH_ID, uuid);
-
- //clear animation flags
- avatarp = (LLVOAvatar *)gObjectList.findObject(uuid);
-
- if (!avatarp)
- {
- // no agent by this ID...error?
- LL_WARNS("Messaging") << "Received animation state for unknown avatar" << uuid << LL_ENDL;
- return;
- }
-
- S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationList);
- S32 num_source_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationSourceList);
-
- avatarp->mSignaledAnimations.clear();
-
- if (avatarp->isSelf())
- {
- LLUUID object_id;
-
- for( S32 i = 0; i < num_blocks; i++ )
- {
- mesgsys->getUUIDFast(_PREHASH_AnimationList, _PREHASH_AnimID, animation_id, i);
- mesgsys->getS32Fast(_PREHASH_AnimationList, _PREHASH_AnimSequenceID, anim_sequence_id, i);
-
- LL_DEBUGS("Messaging") << "Anim sequence ID: " << anim_sequence_id << LL_ENDL;
-
- avatarp->mSignaledAnimations[animation_id] = anim_sequence_id;
-
- if (i < num_source_blocks)
- {
- mesgsys->getUUIDFast(_PREHASH_AnimationSourceList, _PREHASH_ObjectID, object_id, i);
-
- LLViewerObject* object = gObjectList.findObject(object_id);
- if (object)
- {
- object->mFlags |= FLAGS_ANIM_SOURCE;
-
- BOOL anim_found = FALSE;
- LLVOAvatar::AnimSourceIterator anim_it = avatarp->mAnimationSources.find(object_id);
- for (;anim_it != avatarp->mAnimationSources.end(); ++anim_it)
- {
- if (anim_it->second == animation_id)
- {
- anim_found = TRUE;
- break;
- }
- }
-
- if (!anim_found)
- {
- avatarp->mAnimationSources.insert(LLVOAvatar::AnimationSourceMap::value_type(object_id, animation_id));
- }
- }
- }
- }
- }
- else
- {
- for( S32 i = 0; i < num_blocks; i++ )
- {
- mesgsys->getUUIDFast(_PREHASH_AnimationList, _PREHASH_AnimID, animation_id, i);
- mesgsys->getS32Fast(_PREHASH_AnimationList, _PREHASH_AnimSequenceID, anim_sequence_id, i);
- avatarp->mSignaledAnimations[animation_id] = anim_sequence_id;
- }
- }
-
- if (num_blocks)
- {
- avatarp->processAnimationStateChanges();
- }
-}
-
-void process_avatar_appearance(LLMessageSystem *mesgsys, void **user_data)
-{
- LLUUID uuid;
- mesgsys->getUUIDFast(_PREHASH_Sender, _PREHASH_ID, uuid);
-
- LLVOAvatar* avatarp = (LLVOAvatar *)gObjectList.findObject(uuid);
- if( avatarp )
- {
- avatarp->processAvatarAppearance( mesgsys );
- }
- else
- {
- LL_WARNS("Messaging") << "avatar_appearance sent for unknown avatar " << uuid << LL_ENDL;
- }
-}
-
-void process_camera_constraint(LLMessageSystem *mesgsys, void **user_data)
-{
- LLVector4 cameraCollidePlane;
- mesgsys->getVector4Fast(_PREHASH_CameraCollidePlane, _PREHASH_Plane, cameraCollidePlane);
-
- gAgent.setCameraCollidePlane(cameraCollidePlane);
-}
-
-void near_sit_object(BOOL success, void *data)
-{
- if (success)
- {
- // Send message to sit on object
- gMessageSystem->newMessageFast(_PREHASH_AgentSit);
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- gAgent.sendReliableMessage();
- }
-}
-
-void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data)
-{
- LLVector3 sitPosition;
- LLQuaternion sitRotation;
- LLUUID sitObjectID;
- BOOL use_autopilot;
- mesgsys->getUUIDFast(_PREHASH_SitObject, _PREHASH_ID, sitObjectID);
- mesgsys->getBOOLFast(_PREHASH_SitTransform, _PREHASH_AutoPilot, use_autopilot);
- mesgsys->getVector3Fast(_PREHASH_SitTransform, _PREHASH_SitPosition, sitPosition);
- mesgsys->getQuatFast(_PREHASH_SitTransform, _PREHASH_SitRotation, sitRotation);
- LLVector3 camera_eye;
- mesgsys->getVector3Fast(_PREHASH_SitTransform, _PREHASH_CameraEyeOffset, camera_eye);
- LLVector3 camera_at;
- mesgsys->getVector3Fast(_PREHASH_SitTransform, _PREHASH_CameraAtOffset, camera_at);
- BOOL force_mouselook;
- mesgsys->getBOOLFast(_PREHASH_SitTransform, _PREHASH_ForceMouselook, force_mouselook);
-
- LLVOAvatar* avatar = gAgent.getAvatarObject();
-
- if (avatar && dist_vec_squared(camera_eye, camera_at) > 0.0001f)
- {
- gAgent.setSitCamera(sitObjectID, camera_eye, camera_at);
- }
-
- gAgent.setForceMouselook(force_mouselook);
-
- LLViewerObject* object = gObjectList.findObject(sitObjectID);
- if (object)
- {
- LLVector3 sit_spot = object->getPositionAgent() + (sitPosition * object->getRotation());
- if (!use_autopilot || (avatar && avatar->isSitting() && avatar->getRoot() == object->getRoot()))
- {
- //we're already sitting on this object, so don't autopilot
- }
- else
- {
- gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(sit_spot), "Sit", &sitRotation, near_sit_object, NULL, 0.5f);
- }
- }
- else
- {
- LL_WARNS("Messaging") << "Received sit approval for unknown object " << sitObjectID << LL_ENDL;
- }
-}
-
-void process_clear_follow_cam_properties(LLMessageSystem *mesgsys, void **user_data)
-{
- LLUUID source_id;
-
- mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, source_id);
-
- LLFollowCamMgr::removeFollowCamParams(source_id);
-}
-
-void process_set_follow_cam_properties(LLMessageSystem *mesgsys, void **user_data)
-{
- S32 type;
- F32 value;
- bool settingPosition = false;
- bool settingFocus = false;
- bool settingFocusOffset = false;
- LLVector3 position;
- LLVector3 focus;
- LLVector3 focus_offset;
-
- LLUUID source_id;
-
- mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, source_id);
-
- LLViewerObject* objectp = gObjectList.findObject(source_id);
- if (objectp)
- {
- objectp->mFlags |= FLAGS_CAMERA_SOURCE;
- }
-
- S32 num_objects = mesgsys->getNumberOfBlocks("CameraProperty");
- for (S32 block_index = 0; block_index < num_objects; block_index++)
- {
- mesgsys->getS32("CameraProperty", "Type", type, block_index);
- mesgsys->getF32("CameraProperty", "Value", value, block_index);
- switch(type)
- {
- case FOLLOWCAM_PITCH:
- LLFollowCamMgr::setPitch(source_id, value);
- break;
- case FOLLOWCAM_FOCUS_OFFSET_X:
- focus_offset.mV[VX] = value;
- settingFocusOffset = true;
- break;
- case FOLLOWCAM_FOCUS_OFFSET_Y:
- focus_offset.mV[VY] = value;
- settingFocusOffset = true;
- break;
- case FOLLOWCAM_FOCUS_OFFSET_Z:
- focus_offset.mV[VZ] = value;
- settingFocusOffset = true;
- break;
- case FOLLOWCAM_POSITION_LAG:
- LLFollowCamMgr::setPositionLag(source_id, value);
- break;
- case FOLLOWCAM_FOCUS_LAG:
- LLFollowCamMgr::setFocusLag(source_id, value);
- break;
- case FOLLOWCAM_DISTANCE:
- LLFollowCamMgr::setDistance(source_id, value);
- break;
- case FOLLOWCAM_BEHINDNESS_ANGLE:
- LLFollowCamMgr::setBehindnessAngle(source_id, value);
- break;
- case FOLLOWCAM_BEHINDNESS_LAG:
- LLFollowCamMgr::setBehindnessLag(source_id, value);
- break;
- case FOLLOWCAM_POSITION_THRESHOLD:
- LLFollowCamMgr::setPositionThreshold(source_id, value);
- break;
- case FOLLOWCAM_FOCUS_THRESHOLD:
- LLFollowCamMgr::setFocusThreshold(source_id, value);
- break;
- case FOLLOWCAM_ACTIVE:
- //if 1, set using followcam,.
- LLFollowCamMgr::setCameraActive(source_id, value != 0.f);
- break;
- case FOLLOWCAM_POSITION_X:
- settingPosition = true;
- position.mV[ 0 ] = value;
- break;
- case FOLLOWCAM_POSITION_Y:
- settingPosition = true;
- position.mV[ 1 ] = value;
- break;
- case FOLLOWCAM_POSITION_Z:
- settingPosition = true;
- position.mV[ 2 ] = value;
- break;
- case FOLLOWCAM_FOCUS_X:
- settingFocus = true;
- focus.mV[ 0 ] = value;
- break;
- case FOLLOWCAM_FOCUS_Y:
- settingFocus = true;
- focus.mV[ 1 ] = value;
- break;
- case FOLLOWCAM_FOCUS_Z:
- settingFocus = true;
- focus.mV[ 2 ] = value;
- break;
- case FOLLOWCAM_POSITION_LOCKED:
- LLFollowCamMgr::setPositionLocked(source_id, value != 0.f);
- break;
- case FOLLOWCAM_FOCUS_LOCKED:
- LLFollowCamMgr::setFocusLocked(source_id, value != 0.f);
- break;
-
- default:
- break;
- }
- }
-
- if ( settingPosition )
- {
- LLFollowCamMgr::setPosition(source_id, position);
- }
- if ( settingFocus )
- {
- LLFollowCamMgr::setFocus(source_id, focus);
- }
- if ( settingFocusOffset )
- {
- LLFollowCamMgr::setFocusOffset(source_id, focus_offset);
- }
-}
-//end Ventrella
-
-
-// Culled from newsim lltask.cpp
-void process_name_value(LLMessageSystem *mesgsys, void **user_data)
-{
- std::string temp_str;
- LLUUID id;
- S32 i, num_blocks;
-
- mesgsys->getUUIDFast(_PREHASH_TaskData, _PREHASH_ID, id);
-
- LLViewerObject* object = gObjectList.findObject(id);
-
- if (object)
- {
- num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_NameValueData);
- for (i = 0; i < num_blocks; i++)
- {
- mesgsys->getStringFast(_PREHASH_NameValueData, _PREHASH_NVPair, temp_str, i);
- LL_INFOS("Messaging") << "Added to object Name Value: " << temp_str << LL_ENDL;
- object->addNVPair(temp_str);
- }
- }
- else
- {
- LL_INFOS("Messaging") << "Can't find object " << id << " to add name value pair" << LL_ENDL;
- }
-}
-
-void process_remove_name_value(LLMessageSystem *mesgsys, void **user_data)
-{
- std::string temp_str;
- LLUUID id;
- S32 i, num_blocks;
-
- mesgsys->getUUIDFast(_PREHASH_TaskData, _PREHASH_ID, id);
-
- LLViewerObject* object = gObjectList.findObject(id);
-
- if (object)
- {
- num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_NameValueData);
- for (i = 0; i < num_blocks; i++)
- {
- mesgsys->getStringFast(_PREHASH_NameValueData, _PREHASH_NVPair, temp_str, i);
- LL_INFOS("Messaging") << "Removed from object Name Value: " << temp_str << LL_ENDL;
- object->removeNVPair(temp_str);
- }
- }
- else
- {
- LL_INFOS("Messaging") << "Can't find object " << id << " to remove name value pair" << LL_ENDL;
- }
-}
-
-void process_kick_user(LLMessageSystem *msg, void** /*user_data*/)
-{
- std::string message;
-
- msg->getStringFast(_PREHASH_UserInfo, _PREHASH_Reason, message);
-
- LLAppViewer::instance()->forceDisconnect(message);
-}
-
-
-/*
-void process_user_list_reply(LLMessageSystem *msg, void **user_data)
-{
- LLUserList::processUserListReply(msg, user_data);
- return;
- char firstname[MAX_STRING+1];
- char lastname[MAX_STRING+1];
- U8 status;
- S32 user_count;
-
- user_count = msg->getNumberOfBlocks("UserBlock");
-
- for (S32 i = 0; i < user_count; i++)
- {
- msg->getData("UserBlock", i, "FirstName", firstname);
- msg->getData("UserBlock", i, "LastName", lastname);
- msg->getData("UserBlock", i, "Status", &status);
-
- if (status & 0x01)
- {
- dialog_friends_add_friend(buffer, TRUE);
- }
- else
- {
- dialog_friends_add_friend(buffer, FALSE);
- }
- }
-
- dialog_friends_done_adding();
-}
-*/
-
-// this is not handled in processUpdateMessage
-/*
-void process_time_dilation(LLMessageSystem *msg, void **user_data)
-{
- // get the time_dilation
- U16 foo;
- msg->getData("TimeDilation", "TimeDilation", &foo);
- F32 time_dilation = ((F32) foo) / 65535.f;
-
- // get the pointer to the right region
- U32 ip = msg->getSenderIP();
- U32 port = msg->getSenderPort();
- LLViewerRegion *regionp = LLWorld::getInstance()->getRegion(ip, port);
- if (regionp)
- {
- regionp->setTimeDilation(time_dilation);
- }
-}
-*/
-
-
-
-void process_money_balance_reply( LLMessageSystem* msg, void** )
-{
- S32 balance = 0;
- S32 credit = 0;
- S32 committed = 0;
- std::string desc;
-
- msg->getS32("MoneyData", "MoneyBalance", balance);
- msg->getS32("MoneyData", "SquareMetersCredit", credit);
- msg->getS32("MoneyData", "SquareMetersCommitted", committed);
- msg->getStringFast(_PREHASH_MoneyData, _PREHASH_Description, desc);
- LL_INFOS("Messaging") << "L$, credit, committed: " << balance << " " << credit << " "
- << committed << LL_ENDL;
-
- if (gStatusBar)
- {
- S32 old_balance = gStatusBar->getBalance();
-
- // This is an update, not the first transmission of balance
- if (old_balance != 0)
- {
- // this is actually an update
- if (balance > old_balance)
- {
- LLFirstUse::useBalanceIncrease(balance - old_balance);
- }
- else if (balance < old_balance)
- {
- LLFirstUse::useBalanceDecrease(balance - old_balance);
- }
- }
-
- gStatusBar->setBalance(balance);
- gStatusBar->setLandCredit(credit);
- gStatusBar->setLandCommitted(committed);
- }
-
- LLUUID tid;
- msg->getUUID("MoneyData", "TransactionID", tid);
- static std::deque<LLUUID> recent;
- if(!desc.empty() && gSavedSettings.getBOOL("NotifyMoneyChange")
- && (std::find(recent.rbegin(), recent.rend(), tid) == recent.rend()))
- {
- // Make the user confirm the transaction, since they might
- // have missed something during an event.
- // *TODO: Translate
- LLSD args;
- args["MESSAGE"] = desc;
- LLNotifications::instance().add("SystemMessage", args);
-
- // Once the 'recent' container gets large enough, chop some
- // off the beginning.
- const U32 MAX_LOOKBACK = 30;
- const S32 POP_FRONT_SIZE = 12;
- if(recent.size() > MAX_LOOKBACK)
- {
- LL_DEBUGS("Messaging") << "Removing oldest transaction records" << LL_ENDL;
- recent.erase(recent.begin(), recent.begin() + POP_FRONT_SIZE);
- }
- //LL_DEBUGS("Messaging") << "Pushing back transaction " << tid << LL_ENDL;
- recent.push_back(tid);
- }
-}
-
-bool handle_special_notification_callback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
-
- if (0 == option)
- {
- // set the preference to the maturity of the region we're calling
- int preferredMaturity = notification["payload"]["_region_access"].asInteger();
- gSavedSettings.setU32("PreferredMaturity", preferredMaturity);
- gAgent.sendMaturityPreferenceToServer(preferredMaturity);
-
- }
-
- return false;
-}
-
-// some of the server notifications need special handling. This is where we do that.
-bool handle_special_notification(std::string notificationID, LLSD& llsdBlock)
-{
- int regionAccess = llsdBlock["_region_access"].asInteger();
- llsdBlock["REGIONMATURITY"] = LLViewerRegion::accessToString(regionAccess);
-
- // we're going to throw the LLSD in there in case anyone ever wants to use it
- LLNotifications::instance().add(notificationID+"_Notify", llsdBlock);
-
- if (regionAccess == SIM_ACCESS_MATURE)
- {
- if (gAgent.isTeen())
- {
- LLNotifications::instance().add(notificationID+"_KB", llsdBlock);
- return true;
- }
- else if (gAgent.prefersPG())
- {
- LLNotifications::instance().add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback);
- return true;
- }
- }
- else if (regionAccess == SIM_ACCESS_ADULT)
- {
- if (!gAgent.isAdult())
- {
- LLNotifications::instance().add(notificationID+"_KB", llsdBlock);
- return true;
- }
- else if (gAgent.prefersPG() || gAgent.prefersMature())
- {
- LLNotifications::instance().add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback);
- return true;
- }
- }
- return false;
-}
-
-bool attempt_standard_notification(LLMessageSystem* msgsystem)
-{
- // if we have additional alert data
- if (msgsystem->has(_PREHASH_AlertInfo) && msgsystem->getNumberOfBlocksFast(_PREHASH_AlertInfo) > 0)
- {
- // notification was specified using the new mechanism, so we can just handle it here
- std::string notificationID;
- std::string llsdRaw;
- LLSD llsdBlock;
- msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, notificationID);
- msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_ExtraParams, llsdRaw);
- if (llsdRaw.length())
- {
- std::istringstream llsdData(llsdRaw);
- if (!LLSDSerialize::deserialize(llsdBlock, llsdData, llsdRaw.length()))
- {
- llwarns << "attempt_standard_notification: Attempted to read notification parameter data into LLSD but failed:" << llsdRaw << llendl;
- }
- }
-
- if (
- (notificationID == "RegionEntryAccessBlocked") ||
- (notificationID == "LandClaimAccessBlocked") ||
- (notificationID == "LandBuyAccessBlocked")
- )
- {
- /*---------------------------------------------------------------------
- (Commented so a grep will find the notification strings, since
- we construct them on the fly; if you add additional notifications,
- please update the comment.)
-
- Could throw any of the following notifications:
-
- RegionEntryAccessBlocked
- RegionEntryAccessBlocked_Notify
- RegionEntryAccessBlocked_Change
- RegionEntryAccessBlocked_KB
- LandClaimAccessBlocked
- LandClaimAccessBlocked_Notify
- LandClaimAccessBlocked_Change
- LandClaimAccessBlocked_KB
- LandBuyAccessBlocked
- LandBuyAccessBlocked_Notify
- LandBuyAccessBlocked_Change
- LandBuyAccessBlocked_KB
-
- -----------------------------------------------------------------------*/
- if (handle_special_notification(notificationID, llsdBlock))
- {
- return true;
- }
- }
-
- LLNotifications::instance().add(notificationID, llsdBlock);
- return true;
- }
- return false;
-}
-
-
-void process_agent_alert_message(LLMessageSystem* msgsystem, void** user_data)
-{
- // make sure the cursor is back to the usual default since the
- // alert is probably due to some kind of error.
- gViewerWindow->getWindow()->resetBusyCount();
-
- if (!attempt_standard_notification(msgsystem))
- {
- BOOL modal = FALSE;
- msgsystem->getBOOL("AlertData", "Modal", modal);
- std::string buffer;
- msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer);
- process_alert_core(buffer, modal);
- }
-}
-
-// The only difference between this routine and the previous is the fact that
-// for this routine, the modal parameter is always false. Sadly, for the message
-// handled by this routine, there is no "Modal" parameter on the message, and
-// there's no API to tell if a message has the given parameter or not.
-// So we can't handle the messages with the same handler.
-void process_alert_message(LLMessageSystem *msgsystem, void **user_data)
-{
- // make sure the cursor is back to the usual default since the
- // alert is probably due to some kind of error.
- gViewerWindow->getWindow()->resetBusyCount();
-
- if (!attempt_standard_notification(msgsystem))
- {
- BOOL modal = FALSE;
- std::string buffer;
- msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer);
- process_alert_core(buffer, modal);
- }
-}
-
-void process_alert_core(const std::string& message, BOOL modal)
-{
- // HACK -- handle callbacks for specific alerts
- if ( message == "You died and have been teleported to your home location")
- {
- LLViewerStats::getInstance()->incStat(LLViewerStats::ST_KILLED_COUNT);
- }
- else if( message == "Home position set." )
- {
- // save the home location image to disk
- std::string snap_filename = gDirUtilp->getLindenUserDir();
- snap_filename += gDirUtilp->getDirDelimiter();
- snap_filename += SCREEN_HOME_FILENAME;
- gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight(), FALSE, FALSE);
- }
-
- const std::string ALERT_PREFIX("ALERT: ");
- const std::string NOTIFY_PREFIX("NOTIFY: ");
- if (message.find(ALERT_PREFIX) == 0)
- {
- // Allow the server to spawn a named alert so that server alerts can be
- // translated out of English.
- std::string alert_name(message.substr(ALERT_PREFIX.length()));
- LLNotifications::instance().add(alert_name);
- }
- else if (message.find(NOTIFY_PREFIX) == 0)
- {
- // Allow the server to spawn a named notification so that server notifications can be
- // translated out of English.
- std::string notify_name(message.substr(NOTIFY_PREFIX.length()));
- LLNotifications::instance().add(notify_name);
- }
- else if (message[0] == '/')
- {
- // System message is important, show in upper-right box not tip
- std::string text(message.substr(1));
- LLSD args;
- if (text.substr(0,17) == "RESTART_X_MINUTES")
- {
- S32 mins = 0;
- LLStringUtil::convertToS32(text.substr(18), mins);
- args["MINUTES"] = llformat("%d",mins);
- LLNotifications::instance().add("RegionRestartMinutes", args);
- }
- else if (text.substr(0,17) == "RESTART_X_SECONDS")
- {
- S32 secs = 0;
- LLStringUtil::convertToS32(text.substr(18), secs);
- args["SECONDS"] = llformat("%d",secs);
- LLNotifications::instance().add("RegionRestartSeconds", args);
- }
- else
- {
- std::string new_msg =LLNotifications::instance().getGlobalString(text);
- args["MESSAGE"] = new_msg;
- LLNotifications::instance().add("SystemMessage", args);
- }
- }
- else if (modal)
- {
- LLSD args;
- std::string new_msg =LLNotifications::instance().getGlobalString(message);
- args["ERROR_MESSAGE"] = new_msg;
- LLNotifications::instance().add("ErrorMessage", args);
- }
- else
- {
- LLSD args;
- std::string new_msg =LLNotifications::instance().getGlobalString(message);
- args["MESSAGE"] = new_msg;
- LLNotifications::instance().add("SystemMessageTip", args);
- }
-}
-
-mean_collision_list_t gMeanCollisionList;
-time_t gLastDisplayedTime = 0;
-
-void handle_show_mean_events(void *)
-{
- if (gNoRender)
- {
- return;
- }
- LLFloaterReg::showInstance("bumps");
- //LLFloaterBump::showInstance();
-}
-
-void mean_name_callback(const LLUUID &id, const std::string& first, const std::string& last, BOOL always_false)
-{
- if (gNoRender)
- {
- return;
- }
-
- static const U32 max_collision_list_size = 20;
- if (gMeanCollisionList.size() > max_collision_list_size)
- {
- mean_collision_list_t::iterator iter = gMeanCollisionList.begin();
- for (U32 i=0; i<max_collision_list_size; i++) iter++;
- for_each(iter, gMeanCollisionList.end(), DeletePointer());
- gMeanCollisionList.erase(iter, gMeanCollisionList.end());
- }
-
- for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin();
- iter != gMeanCollisionList.end(); ++iter)
- {
- LLMeanCollisionData *mcd = *iter;
- if (mcd->mPerp == id)
- {
- mcd->mFirstName = first;
- mcd->mLastName = last;
- }
- }
-}
-
-void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **user_data)
-{
- if (gAgent.inPrelude())
- {
- // In prelude, bumping is OK. This dialog is rather confusing to
- // newbies, so we don't show it. Drop the packet on the floor.
- return;
- }
-
- // make sure the cursor is back to the usual default since the
- // alert is probably due to some kind of error.
- gViewerWindow->getWindow()->resetBusyCount();
-
- LLUUID perp;
- U32 time;
- U8 u8type;
- EMeanCollisionType type;
- F32 mag;
-
- S32 i, num = msgsystem->getNumberOfBlocks(_PREHASH_MeanCollision);
-
- for (i = 0; i < num; i++)
- {
- msgsystem->getUUIDFast(_PREHASH_MeanCollision, _PREHASH_Perp, perp);
- msgsystem->getU32Fast(_PREHASH_MeanCollision, _PREHASH_Time, time);
- msgsystem->getF32Fast(_PREHASH_MeanCollision, _PREHASH_Mag, mag);
- msgsystem->getU8Fast(_PREHASH_MeanCollision, _PREHASH_Type, u8type);
-
- type = (EMeanCollisionType)u8type;
-
- BOOL b_found = FALSE;
-
- for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin();
- iter != gMeanCollisionList.end(); ++iter)
- {
- LLMeanCollisionData *mcd = *iter;
- if ((mcd->mPerp == perp) && (mcd->mType == type))
- {
- mcd->mTime = time;
- mcd->mMag = mag;
- b_found = TRUE;
- break;
- }
- }
-
- if (!b_found)
- {
- LLMeanCollisionData *mcd = new LLMeanCollisionData(gAgentID, perp, time, type, mag);
- gMeanCollisionList.push_front(mcd);
- const BOOL is_group = FALSE;
- gCacheName->get(perp, is_group, &mean_name_callback);
- }
- }
-}
-
-void process_frozen_message(LLMessageSystem *msgsystem, void **user_data)
-{
- // make sure the cursor is back to the usual default since the
- // alert is probably due to some kind of error.
- gViewerWindow->getWindow()->resetBusyCount();
- BOOL b_frozen;
-
- msgsystem->getBOOL("FrozenData", "Data", b_frozen);
-
- // TODO: make being frozen change view
- if (b_frozen)
- {
- }
- else
- {
- }
-}
-
-// do some extra stuff once we get our economy data
-void process_economy_data(LLMessageSystem *msg, void** /*user_data*/)
-{
- LLGlobalEconomy::processEconomyData(msg, LLGlobalEconomy::Singleton::getInstance());
-
- S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
-
- LL_INFOS_ONCE("Messaging") << "EconomyData message arrived; upload cost is L$" << upload_cost << LL_ENDL;
-
- gMenuHolder->childSetLabelArg("Upload Image", "[COST]", llformat("%d", upload_cost));
- gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", llformat("%d", upload_cost));
- gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", llformat("%d", upload_cost));
- gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", llformat("%d", upload_cost));
-}
-
-void notify_cautioned_script_question(const LLSD& notification, const LLSD& response, S32 orig_questions, BOOL granted)
-{
- // only continue if at least some permissions were requested
- if (orig_questions)
- {
- // check to see if the person we are asking
-
- // "'[OBJECTNAME]', an object owned by '[OWNERNAME]',
- // located in [REGIONNAME] at [REGIONPOS],
- // has been <granted|denied> permission to: [PERMISSIONS]."
-
- LLUIString notice(LLTrans::getString(granted ? "ScriptQuestionCautionChatGranted" : "ScriptQuestionCautionChatDenied"));
-
- // always include the object name and owner name
- notice.setArg("[OBJECTNAME]", notification["payload"]["object_name"].asString());
- notice.setArg("[OWNERNAME]", notification["payload"]["owner_name"].asString());
-
- // try to lookup viewerobject that corresponds to the object that
- // requested permissions (here, taskid->requesting object id)
- BOOL foundpos = FALSE;
- LLViewerObject* viewobj = gObjectList.findObject(notification["payload"]["task_id"].asUUID());
- if (viewobj)
- {
- // found the viewerobject, get it's position in its region
- LLVector3 objpos(viewobj->getPosition());
-
- // try to lookup the name of the region the object is in
- LLViewerRegion* viewregion = viewobj->getRegion();
- if (viewregion)
- {
- // got the region, so include the region and 3d coordinates of the object
- notice.setArg("[REGIONNAME]", viewregion->getName());
- std::string formatpos = llformat("%.1f, %.1f,%.1f", objpos[VX], objpos[VY], objpos[VZ]);
- notice.setArg("[REGIONPOS]", formatpos);
-
- foundpos = TRUE;
- }
- }
-
- if (!foundpos)
- {
- // unable to determine location of the object
- notice.setArg("[REGIONNAME]", "(unknown region)");
- notice.setArg("[REGIONPOS]", "(unknown position)");
- }
-
- // check each permission that was requested, and list each
- // permission that has been flagged as a caution permission
- BOOL caution = FALSE;
- S32 count = 0;
- std::string perms;
- for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++)
- {
- if ((orig_questions & LSCRIPTRunTimePermissionBits[i]) && SCRIPT_QUESTION_IS_CAUTION[i])
- {
- count++;
- caution = TRUE;
-
- // add a comma before the permission description if it is not the first permission
- // added to the list or the last permission to check
- if ((count > 1) && (i < SCRIPT_PERMISSION_EOF))
- {
- perms.append(", ");
- }
-
- perms.append(LLTrans::getString(SCRIPT_QUESTIONS[i]));
- }
- }
-
- notice.setArg("[PERMISSIONS]", perms);
-
- // log a chat message as long as at least one requested permission
- // is a caution permission
- if (caution)
- {
- LLChat chat(notice.getString());
- LLFloaterChat::addChat(chat, FALSE, FALSE);
- }
- }
-}
-
-bool script_question_cb(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
- LLMessageSystem *msg = gMessageSystem;
- S32 orig = notification["payload"]["questions"].asInteger();
- S32 new_questions = orig;
-
- // check whether permissions were granted or denied
- BOOL allowed = TRUE;
- // the "yes/accept" button is the first button in the template, making it button 0
- // if any other button was clicked, the permissions were denied
- if (option != 0)
- {
- new_questions = 0;
- allowed = FALSE;
- }
-
- LLUUID task_id = notification["payload"]["task_id"].asUUID();
- LLUUID item_id = notification["payload"]["item_id"].asUUID();
-
- // reply with the permissions granted or denied
- msg->newMessageFast(_PREHASH_ScriptAnswerYes);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_Data);
- msg->addUUIDFast(_PREHASH_TaskID, task_id);
- msg->addUUIDFast(_PREHASH_ItemID, item_id);
- msg->addS32Fast(_PREHASH_Questions, new_questions);
- msg->sendReliable(LLHost(notification["payload"]["sender"].asString()));
-
- // only log a chat message if caution prompts are enabled
- if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
- {
- // log a chat message, if appropriate
- notify_cautioned_script_question(notification, response, orig, allowed);
- }
-
- if ( response["Mute"] ) // mute
- {
- LLMuteList::getInstance()->add(LLMute(item_id, notification["payload"]["object_name"].asString(), LLMute::OBJECT));
-
- // purge the message queue of any previously queued requests from the same source. DEV-4879
- class OfferMatcher : public LLNotifyBoxView::Matcher
- {
- public:
- OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {}
- BOOL matches(const LLNotificationPtr notification) const
- {
- if (notification->getName() == "ScriptQuestionCaution"
- || notification->getName() == "ScriptQuestion")
- {
- return (notification->getPayload()["item_id"].asUUID() == blocked_id);
- }
- return FALSE;
- }
- private:
- const LLUUID& blocked_id;
- };
- // should do this via the channel
- gNotifyBoxView->purgeMessagesMatching(OfferMatcher(item_id));
- }
-
- if (response["Details"])
- {
- // respawn notification...
- LLNotifications::instance().add(notification["name"], notification["substitutions"], notification["payload"]);
-
- // ...with description on top
- LLNotifications::instance().add("DebitPermissionDetails");
- }
- return false;
-}
-static LLNotificationFunctorRegistration script_question_cb_reg_1("ScriptQuestion", script_question_cb);
-static LLNotificationFunctorRegistration script_question_cb_reg_2("ScriptQuestionCaution", script_question_cb);
-
-void process_script_question(LLMessageSystem *msg, void **user_data)
-{
- // *TODO: Translate owner name -> [FIRST] [LAST]
-
- LLHost sender = msg->getSender();
-
- LLUUID taskid;
- LLUUID itemid;
- S32 questions;
- std::string object_name;
- std::string owner_name;
-
- // taskid -> object key of object requesting permissions
- msg->getUUIDFast(_PREHASH_Data, _PREHASH_TaskID, taskid );
- // itemid -> script asset key of script requesting permissions
- msg->getUUIDFast(_PREHASH_Data, _PREHASH_ItemID, itemid );
- msg->getStringFast(_PREHASH_Data, _PREHASH_ObjectName, object_name);
- msg->getStringFast(_PREHASH_Data, _PREHASH_ObjectOwner, owner_name);
- msg->getS32Fast(_PREHASH_Data, _PREHASH_Questions, questions );
-
- // Special case. If the objects are owned by this agent, throttle per-object instead
- // of per-owner. It's common for residents to reset a ton of scripts that re-request
- // permissions, as with tier boxes. UUIDs can't be valid agent names and vice-versa,
- // so we'll reuse the same namespace for both throttle types.
- std::string throttle_name = owner_name;
- std::string self_name;
- LLAgentUI::buildName( self_name );
- if( owner_name == self_name )
- {
- throttle_name = taskid.getString();
- }
-
- // don't display permission requests if this object is muted
- if (LLMuteList::getInstance()->isMuted(taskid)) return;
-
- // throttle excessive requests from any specific user's scripts
- typedef LLKeyThrottle<std::string> LLStringThrottle;
- static LLStringThrottle question_throttle( LLREQUEST_PERMISSION_THROTTLE_LIMIT, LLREQUEST_PERMISSION_THROTTLE_INTERVAL );
-
- switch (question_throttle.noteAction(throttle_name))
- {
- case LLStringThrottle::THROTTLE_NEWLY_BLOCKED:
- LL_INFOS("Messaging") << "process_script_question throttled"
- << " owner_name:" << owner_name
- << LL_ENDL;
- // Fall through
-
- case LLStringThrottle::THROTTLE_BLOCKED:
- // Escape altogether until we recover
- return;
-
- case LLStringThrottle::THROTTLE_OK:
- break;
- }
-
- std::string script_question;
- if (questions)
- {
- BOOL caution = FALSE;
- S32 count = 0;
- LLSD args;
- args["OBJECTNAME"] = object_name;
- args["NAME"] = owner_name;
-
- // check the received permission flags against each permission
- for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++)
- {
- if (questions & LSCRIPTRunTimePermissionBits[i])
- {
- count++;
- script_question += " " + LLTrans::getString(SCRIPT_QUESTIONS[i]) + "\n";
-
- // check whether permission question should cause special caution dialog
- caution |= (SCRIPT_QUESTION_IS_CAUTION[i]);
- }
- }
- args["QUESTIONS"] = script_question;
-
- LLSD payload;
- payload["task_id"] = taskid;
- payload["item_id"] = itemid;
- payload["sender"] = sender.getIPandPort();
- payload["questions"] = questions;
- payload["object_name"] = object_name;
- payload["owner_name"] = owner_name;
-
- // check whether cautions are even enabled or not
- if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
- {
- // display the caution permissions prompt
- LLNotifications::instance().add(caution ? "ScriptQuestionCaution" : "ScriptQuestion", args, payload);
- }
- else
- {
- // fall back to default behavior if cautions are entirely disabled
- LLNotifications::instance().add("ScriptQuestion", args, payload);
- }
-
- }
-}
-
-
-void process_derez_container(LLMessageSystem *msg, void**)
-{
- LL_WARNS("Messaging") << "call to deprecated process_derez_container" << LL_ENDL;
-}
-
-void container_inventory_arrived(LLViewerObject* object,
- InventoryObjectList* inventory,
- S32 serial_num,
- void* data)
-{
- LL_DEBUGS("Messaging") << "container_inventory_arrived()" << LL_ENDL;
- if( gAgent.cameraMouselook() )
- {
- gAgent.changeCameraToDefault();
- }
-
- LLFloaterInventory* view = LLFloaterInventory::getActiveInventory();
-
- if (inventory->size() > 2)
- {
- // create a new inventory category to put this in
- LLUUID cat_id;
- cat_id = gInventory.createNewCategory(gInventory.getRootFolderID(),
- LLAssetType::AT_NONE,
- LLTrans::getString("AcquiredItems"));
-
- InventoryObjectList::const_iterator it = inventory->begin();
- InventoryObjectList::const_iterator end = inventory->end();
- for ( ; it != end; ++it)
- {
- if ((*it)->getType() != LLAssetType::AT_CATEGORY &&
- (*it)->getType() != LLAssetType::AT_ROOT_CATEGORY)
- {
- LLInventoryObject* obj = (LLInventoryObject*)(*it);
- LLInventoryItem* item = (LLInventoryItem*)(obj);
- LLUUID item_id;
- item_id.generate();
- time_t creation_date_utc = time_corrected();
- LLPointer<LLViewerInventoryItem> new_item
- = new LLViewerInventoryItem(item_id,
- cat_id,
- item->getPermissions(),
- item->getAssetUUID(),
- item->getType(),
- item->getInventoryType(),
- item->getName(),
- item->getDescription(),
- LLSaleInfo::DEFAULT,
- item->getFlags(),
- creation_date_utc);
- new_item->updateServer(TRUE);
- gInventory.updateItem(new_item);
- }
- }
- gInventory.notifyObservers();
- if(view)
- {
- view->getPanel()->setSelection(cat_id, TAKE_FOCUS_NO);
- }
- }
- else if (inventory->size() == 2)
- {
- // we're going to get one fake root category as well as the
- // one actual object
- InventoryObjectList::iterator it = inventory->begin();
-
- if ((*it)->getType() == LLAssetType::AT_CATEGORY ||
- (*it)->getType() == LLAssetType::AT_ROOT_CATEGORY)
- {
- ++it;
- }
-
- LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
- LLUUID category = gInventory.findCategoryUUIDForType(item->getType());
-
- LLUUID item_id;
- item_id.generate();
- time_t creation_date_utc = time_corrected();
- LLPointer<LLViewerInventoryItem> new_item
- = new LLViewerInventoryItem(item_id, category,
- item->getPermissions(),
- item->getAssetUUID(),
- item->getType(),
- item->getInventoryType(),
- item->getName(),
- item->getDescription(),
- LLSaleInfo::DEFAULT,
- item->getFlags(),
- creation_date_utc);
- new_item->updateServer(TRUE);
- gInventory.updateItem(new_item);
- gInventory.notifyObservers();
- if(view)
- {
- view->getPanel()->setSelection(item_id, TAKE_FOCUS_NO);
- }
- }
-
- // we've got the inventory, now delete this object if this was a take
- BOOL delete_object = (BOOL)(intptr_t)data;
- LLViewerRegion *region = gAgent.getRegion();
- if (delete_object && region)
- {
- gMessageSystem->newMessageFast(_PREHASH_ObjectDelete);
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- const U8 NO_FORCE = 0;
- gMessageSystem->addU8Fast(_PREHASH_Force, NO_FORCE);
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
- gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID());
- gMessageSystem->sendReliable(region->getHost());
- }
-}
-
-// method to format the time.
-std::string formatted_time(const time_t& the_time)
-{
- std::string dateStr = "["+LLTrans::getString("LTimeWeek")+"] ["
- +LLTrans::getString("LTimeMonth")+"] ["
- +LLTrans::getString("LTimeDay")+"] ["
- +LLTrans::getString("LTimeHour")+"]:["
- +LLTrans::getString("LTimeMin")+"]:["
- +LLTrans::getString("LTimeSec")+"] ["
- +LLTrans::getString("LTimeYear")+"]";
-
- LLSD substitution;
- substitution["datetime"] = (S32) the_time;
- LLStringUtil::format (dateStr, substitution);
- return dateStr;
-}
-
-
-void process_teleport_failed(LLMessageSystem *msg, void**)
-{
- std::string reason;
- std::string big_reason;
- LLSD args;
-
- // if we have additional alert data
- if (msg->has(_PREHASH_AlertInfo) && msg->getSizeFast(_PREHASH_AlertInfo, _PREHASH_Message) > 0)
- {
- // Get the message ID
- msg->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, reason);
- big_reason = LLAgent::sTeleportErrorMessages[reason];
- if ( big_reason.size() > 0 )
- { // Substitute verbose reason from the local map
- args["REASON"] = big_reason;
- }
- else
- { // Nothing found in the map - use what the server returned in the original message block
- msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, reason);
- args["REASON"] = reason;
- }
-
- LLSD llsd_block;
- std::string llsd_raw;
- msg->getStringFast(_PREHASH_AlertInfo, _PREHASH_ExtraParams, llsd_raw);
- if (llsd_raw.length())
- {
- std::istringstream llsd_data(llsd_raw);
- if (!LLSDSerialize::deserialize(llsd_block, llsd_data, llsd_raw.length()))
- {
- llwarns << "process_teleport_failed: Attempted to read alert parameter data into LLSD but failed:" << llsd_raw << llendl;
- }
- else
- {
- // change notification name in this special case
- if (handle_special_notification("RegionEntryAccessBlocked", llsd_block))
- {
- if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE )
- {
- gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
- }
- return;
- }
- }
- }
-
- }
- else
- {
- msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, reason);
-
- big_reason = LLAgent::sTeleportErrorMessages[reason];
- if ( big_reason.size() > 0 )
- { // Substitute verbose reason from the local map
- args["REASON"] = big_reason;
- }
- else
- { // Nothing found in the map - use what the server returned
- args["REASON"] = reason;
- }
- }
-
- LLNotifications::instance().add("CouldNotTeleportReason", args);
-
- // Let the interested parties know that teleport failed.
- LLViewerParcelMgr::getInstance()->onTeleportFailed();
-
- if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE )
- {
- gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
- }
-}
-
-void process_teleport_local(LLMessageSystem *msg,void**)
-{
- LLUUID agent_id;
- msg->getUUIDFast(_PREHASH_Info, _PREHASH_AgentID, agent_id);
- if (agent_id != gAgent.getID())
- {
- LL_WARNS("Messaging") << "Got teleport notification for wrong agent!" << LL_ENDL;
- return;
- }
-
- U32 location_id;
- LLVector3 pos, look_at;
- U32 teleport_flags;
- msg->getU32Fast(_PREHASH_Info, _PREHASH_LocationID, location_id);
- msg->getVector3Fast(_PREHASH_Info, _PREHASH_Position, pos);
- msg->getVector3Fast(_PREHASH_Info, _PREHASH_LookAt, look_at);
- msg->getU32Fast(_PREHASH_Info, _PREHASH_TeleportFlags, teleport_flags);
-
- if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE )
- {
- gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
- }
-
- // Sim tells us whether the new position is off the ground
- if (teleport_flags & TELEPORT_FLAGS_IS_FLYING)
- {
- gAgent.setFlying(TRUE);
- }
- else
- {
- gAgent.setFlying(FALSE);
- }
-
- gAgent.setPositionAgent(pos);
- gAgent.slamLookAt(look_at);
-
- // likewise make sure the camera is behind the avatar
- gAgent.resetView(TRUE, TRUE);
-
- // send camera update to new region
- gAgent.updateCamera();
-
- send_agent_update(TRUE, TRUE);
-
- // Let the interested parties know we've teleported.
- // Vadim *HACK: Agent position seems to get reset (to render position?)
- // on each frame, so we have to pass the new position manually.
- LLViewerParcelMgr::getInstance()->onTeleportFinished(true, gAgent.getPosGlobalFromAgent(pos));
-}
-
-void send_simple_im(const LLUUID& to_id,
- const std::string& message,
- EInstantMessage dialog,
- const LLUUID& id)
-{
- std::string my_name;
- LLAgentUI::buildFullname(my_name);
- send_improved_im(to_id,
- my_name,
- message,
- IM_ONLINE,
- dialog,
- id,
- NO_TIMESTAMP,
- (U8*)EMPTY_BINARY_BUCKET,
- EMPTY_BINARY_BUCKET_SIZE);
-}
-
-void send_group_notice(const LLUUID& group_id,
- const std::string& subject,
- const std::string& message,
- const LLInventoryItem* item)
-{
- // Put this notice into an instant message form.
- // This will mean converting the item to a binary bucket,
- // and the subject/message into a single field.
- std::string my_name;
- LLAgentUI::buildFullname(my_name);
-
- // Combine subject + message into a single string.
- std::ostringstream subject_and_message;
- // TODO: turn all existing |'s into ||'s in subject and message.
- subject_and_message << subject << "|" << message;
-
- // Create an empty binary bucket.
- U8 bin_bucket[MAX_INVENTORY_BUFFER_SIZE];
- U8* bucket_to_send = bin_bucket;
- bin_bucket[0] = '\0';
- S32 bin_bucket_size = EMPTY_BINARY_BUCKET_SIZE;
- // If there is an item being sent, pack it into the binary bucket.
- if (item)
- {
- LLSD item_def;
- item_def["item_id"] = item->getUUID();
- item_def["owner_id"] = item->getPermissions().getOwner();
- std::ostringstream ostr;
- LLSDSerialize::serialize(item_def, ostr, LLSDSerialize::LLSD_XML);
- bin_bucket_size = ostr.str().copy(
- (char*)bin_bucket, ostr.str().size());
- bin_bucket[bin_bucket_size] = '\0';
- }
- else
- {
- bucket_to_send = (U8*) EMPTY_BINARY_BUCKET;
- }
-
-
- send_improved_im(
- group_id,
- my_name,
- subject_and_message.str(),
- IM_ONLINE,
- IM_GROUP_NOTICE,
- LLUUID::null,
- NO_TIMESTAMP,
- bucket_to_send,
- bin_bucket_size);
-}
-
-bool handle_lure_callback(const LLSD& notification, const LLSD& response)
-{
- std::string text = response["message"].asString();
- S32 option = LLNotification::getSelectedOption(notification, response);
-
- if(0 == option)
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_StartLure);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_Info);
- msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in.
- msg->addStringFast(_PREHASH_Message, text);
- for(LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray();
- it != notification["payload"]["ids"].endArray();
- ++it)
- {
- msg->nextBlockFast(_PREHASH_TargetData);
- msg->addUUIDFast(_PREHASH_TargetID, it->asUUID());
- }
- gAgent.sendReliableMessage();
- }
-
- return false;
-}
-
-void handle_lure(const LLUUID& invitee)
-{
- LLDynamicArray<LLUUID> ids;
- ids.push_back(invitee);
- handle_lure(ids);
-}
-
-// Prompt for a message to the invited user.
-void handle_lure(const std::vector<LLUUID>& ids)
-{
- LLSD edit_args;
- edit_args["REGION"] = gAgent.getRegion()->getName();
-
- LLSD payload;
- for (LLDynamicArray<LLUUID>::const_iterator it = ids.begin();
- it != ids.end();
- ++it)
- {
- payload["ids"].append(*it);
- }
- if (gAgent.isGodlike())
- {
- LLNotifications::instance().add("OfferTeleportFromGod", edit_args, payload, handle_lure_callback);
- }
- else
- {
- LLNotifications::instance().add("OfferTeleport", edit_args, payload, handle_lure_callback);
- }
-}
-
-
-void send_improved_im(const LLUUID& to_id,
- const std::string& name,
- const std::string& message,
- U8 offline,
- EInstantMessage dialog,
- const LLUUID& id,
- U32 timestamp,
- const U8* binary_bucket,
- S32 binary_bucket_size)
-{
- pack_instant_message(
- gMessageSystem,
- gAgent.getID(),
- FALSE,
- gAgent.getSessionID(),
- to_id,
- name,
- message,
- offline,
- dialog,
- id,
- 0,
- LLUUID::null,
- gAgent.getPositionAgent(),
- timestamp,
- binary_bucket,
- binary_bucket_size);
- gAgent.sendReliableMessage();
-}
-
-
-void send_places_query(const LLUUID& query_id,
- const LLUUID& trans_id,
- const std::string& query_text,
- U32 query_flags,
- S32 category,
- const std::string& sim_name)
-{
- LLMessageSystem* msg = gMessageSystem;
-
- msg->newMessage("PlacesQuery");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID());
- msg->addUUID("SessionID", gAgent.getSessionID());
- msg->addUUID("QueryID", query_id);
- msg->nextBlock("TransactionData");
- msg->addUUID("TransactionID", trans_id);
- msg->nextBlock("QueryData");
- msg->addString("QueryText", query_text);
- msg->addU32("QueryFlags", query_flags);
- msg->addS8("Category", (S8)category);
- msg->addString("SimName", sim_name);
- gAgent.sendReliableMessage();
-}
-
-
-void process_user_info_reply(LLMessageSystem* msg, void**)
-{
- LLUUID agent_id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- if(agent_id != gAgent.getID())
- {
- LL_WARNS("Messaging") << "process_user_info_reply - "
- << "wrong agent id." << LL_ENDL;
- }
-
- BOOL im_via_email;
- msg->getBOOLFast(_PREHASH_UserData, _PREHASH_IMViaEMail, im_via_email);
- std::string email;
- msg->getStringFast(_PREHASH_UserData, _PREHASH_EMail, email);
- std::string dir_visibility;
- msg->getString( "UserData", "DirectoryVisibility", dir_visibility);
-
- LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email, email);
- LLFloaterPostcard::updateUserInfo(email);
-}
-
-
-//---------------------------------------------------------------------------
-// Script Dialog
-//---------------------------------------------------------------------------
-
-const S32 SCRIPT_DIALOG_MAX_BUTTONS = 12;
-const S32 SCRIPT_DIALOG_BUTTON_STR_SIZE = 24;
-const S32 SCRIPT_DIALOG_MAX_MESSAGE_SIZE = 512;
-const char* SCRIPT_DIALOG_HEADER = "Script Dialog:\n";
-
-bool callback_script_dialog(const LLSD& notification, const LLSD& response)
-{
- LLNotificationForm form(notification["form"]);
- std::string button = LLNotification::getSelectedOptionName(response);
- S32 button_idx = LLNotification::getSelectedOption(notification, response);
- // Didn't click "Ignore"
- if (button_idx != -1)
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessage("ScriptDialogReply");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID());
- msg->addUUID("SessionID", gAgent.getSessionID());
- msg->nextBlock("Data");
- msg->addUUID("ObjectID", notification["payload"]["object_id"].asUUID());
- msg->addS32("ChatChannel", notification["payload"]["chat_channel"].asInteger());
- msg->addS32("ButtonIndex", button_idx);
- msg->addString("ButtonLabel", button);
- msg->sendReliable(LLHost(notification["payload"]["sender"].asString()));
- }
-
- return false;
-}
-static LLNotificationFunctorRegistration callback_script_dialog_reg_1("ScriptDialog", callback_script_dialog);
-static LLNotificationFunctorRegistration callback_script_dialog_reg_2("ScriptDialogGroup", callback_script_dialog);
-
-void process_script_dialog(LLMessageSystem* msg, void**)
-{
- S32 i;
- LLSD payload;
-
- LLUUID object_id;
- msg->getUUID("Data", "ObjectID", object_id);
-
- if (LLMuteList::getInstance()->isMuted(object_id))
- {
- return;
- }
-
- std::string message;
- std::string first_name;
- std::string last_name;
- std::string title;
-
- S32 chat_channel;
- msg->getString("Data", "FirstName", first_name);
- msg->getString("Data", "LastName", last_name);
- msg->getString("Data", "ObjectName", title);
- msg->getString("Data", "Message", message);
- msg->getS32("Data", "ChatChannel", chat_channel);
-
- // unused for now
- LLUUID image_id;
- msg->getUUID("Data", "ImageID", image_id);
-
- payload["sender"] = msg->getSender().getIPandPort();
- payload["object_id"] = object_id;
- payload["chat_channel"] = chat_channel;
-
- // build up custom form
- S32 button_count = msg->getNumberOfBlocks("Buttons");
- if (button_count > SCRIPT_DIALOG_MAX_BUTTONS)
- {
- llwarns << "Too many script dialog buttons - omitting some" << llendl;
- button_count = SCRIPT_DIALOG_MAX_BUTTONS;
- }
-
- LLNotificationForm form;
- for (i = 0; i < button_count; i++)
- {
- std::string tdesc;
- msg->getString("Buttons", "ButtonLabel", tdesc, i);
- form.addElement("button", std::string(tdesc));
- }
-
- LLSD args;
- args["TITLE"] = title;
- args["MESSAGE"] = message;
- LLNotificationPtr notification;
- if (!first_name.empty())
- {
- args["FIRST"] = first_name;
- args["LAST"] = last_name;
- notification = LLNotifications::instance().add(
- LLNotification::Params("ScriptDialog").substitutions(args).payload(payload).form_elements(form.asLLSD()));
- }
- else
- {
- args["GROUPNAME"] = last_name;
- notification = LLNotifications::instance().add(
- LLNotification::Params("ScriptDialogGroup").substitutions(args).payload(payload).form_elements(form.asLLSD()));
- }
-}
-
-//---------------------------------------------------------------------------
-
-
-std::vector<LLSD> gLoadUrlList;
-
-bool callback_load_url(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
-
- if (0 == option)
- {
- LLWeb::loadURL(notification["payload"]["url"].asString());
- }
-
- return false;
-}
-static LLNotificationFunctorRegistration callback_load_url_reg("LoadWebPage", callback_load_url);
-
-
-// We've got the name of the person who owns the object hurling the url.
-// Display confirmation dialog.
-void callback_load_url_name(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
-{
- std::vector<LLSD>::iterator it;
- for (it = gLoadUrlList.begin(); it != gLoadUrlList.end(); )
- {
- LLSD load_url_info = *it;
- if (load_url_info["owner_id"].asUUID() == id)
- {
- it = gLoadUrlList.erase(it);
-
- std::string owner_name;
- if (is_group)
- {
- owner_name = first + LLTrans::getString("Group");
- }
- else
- {
- owner_name = first + " " + last;
- }
-
- // For legacy name-only mutes.
- if (LLMuteList::getInstance()->isMuted(LLUUID::null, owner_name))
- {
- continue;
- }
- LLSD args;
- args["URL"] = load_url_info["url"].asString();
- args["MESSAGE"] = load_url_info["message"].asString();;
- args["OBJECTNAME"] = load_url_info["object_name"].asString();
- args["NAME"] = owner_name;
-
- LLNotifications::instance().add("LoadWebPage", args, load_url_info);
- }
- else
- {
- ++it;
- }
- }
-}
-
-void process_load_url(LLMessageSystem* msg, void**)
-{
- LLUUID object_id;
- LLUUID owner_id;
- BOOL owner_is_group;
- char object_name[256]; /* Flawfinder: ignore */
- char message[256]; /* Flawfinder: ignore */
- char url[256]; /* Flawfinder: ignore */
-
- msg->getString("Data", "ObjectName", 256, object_name);
- msg->getUUID( "Data", "ObjectID", object_id);
- msg->getUUID( "Data", "OwnerID", owner_id);
- msg->getBOOL( "Data", "OwnerIsGroup", owner_is_group);
- msg->getString("Data", "Message", 256, message);
- msg->getString("Data", "URL", 256, url);
-
- LLSD payload;
- payload["object_id"] = object_id;
- payload["owner_id"] = owner_id;
- payload["owner_is_group"] = owner_is_group;
- payload["object_name"] = object_name;
- payload["message"] = message;
- payload["url"] = url;
-
- // URL is safety checked in load_url above
-
- // Check if object or owner is muted
- if (LLMuteList::getInstance()->isMuted(object_id, object_name) ||
- LLMuteList::getInstance()->isMuted(owner_id))
- {
- LL_INFOS("Messaging")<<"Ignoring load_url from muted object/owner."<<LL_ENDL;
- return;
- }
-
- // Add to list of pending name lookups
- gLoadUrlList.push_back(payload);
-
- gCacheName->get(owner_id, owner_is_group, &callback_load_url_name);
-}
-
-
-void callback_download_complete(void** data, S32 result, LLExtStat ext_status)
-{
- std::string* filepath = (std::string*)data;
- LLSD args;
- args["DOWNLOAD_PATH"] = *filepath;
- LLNotifications::instance().add("FinishedRawDownload", args);
- delete filepath;
-}
-
-
-void process_initiate_download(LLMessageSystem* msg, void**)
-{
- LLUUID agent_id;
- msg->getUUID("AgentData", "AgentID", agent_id);
- if (agent_id != gAgent.getID())
- {
- LL_WARNS("Messaging") << "Initiate download for wrong agent" << LL_ENDL;
- return;
- }
-
- std::string sim_filename;
- std::string viewer_filename;
- msg->getString("FileData", "SimFilename", sim_filename);
- msg->getString("FileData", "ViewerFilename", viewer_filename);
-
- if (!gXferManager->validateFileForRequest(viewer_filename))
- {
- llwarns << "SECURITY: Unauthorized download to local file " << viewer_filename << llendl;
- return;
- }
- gXferManager->requestFile(viewer_filename,
- sim_filename,
- LL_PATH_NONE,
- msg->getSender(),
- FALSE, // don't delete remote
- callback_download_complete,
- (void**)new std::string(viewer_filename));
-}
-
-
-void process_script_teleport_request(LLMessageSystem* msg, void**)
-{
- std::string object_name;
- std::string sim_name;
- LLVector3 pos;
- LLVector3 look_at;
-
- msg->getString("Data", "ObjectName", object_name);
- msg->getString("Data", "SimName", sim_name);
- msg->getVector3("Data", "SimPosition", pos);
- msg->getVector3("Data", "LookAt", look_at);
-
- LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance();
- if(instance)
- {
- instance->trackURL(
- sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]);
- LLFloaterReg::showInstance("world_map", "center");
- }
-
- // remove above two lines and replace with below line
- // to re-enable parcel browser for llMapDestination()
- // LLURLDispatcher::dispatch(LLSLURL::buildSLURL(sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]), FALSE);
-
-}
-
-void process_covenant_reply(LLMessageSystem* msg, void**)
-{
- LLUUID covenant_id, estate_owner_id;
- std::string estate_name;
- U32 covenant_timestamp;
- msg->getUUID("Data", "CovenantID", covenant_id);
- msg->getU32("Data", "CovenantTimestamp", covenant_timestamp);
- msg->getString("Data", "EstateName", estate_name);
- msg->getUUID("Data", "EstateOwnerID", estate_owner_id);
-
- LLPanelEstateCovenant::updateEstateName(estate_name);
- LLPanelLandCovenant::updateEstateName(estate_name);
- LLFloaterBuyLand::updateEstateName(estate_name);
-
- std::string owner_name =
- LLSLURL::buildCommand("agent", estate_owner_id, "inspect");
- LLPanelEstateCovenant::updateEstateOwnerName(owner_name);
- LLPanelLandCovenant::updateEstateOwnerName(owner_name);
- LLFloaterBuyLand::updateEstateOwnerName(owner_name);
-
- LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info");
- if (panel)
- {
- panel->updateEstateName(estate_name);
- panel->updateEstateOwnerName(owner_name);
- }
-
- // standard message, not from system
- std::string last_modified;
- if (covenant_timestamp == 0)
- {
- last_modified = LLTrans::getString("covenant_last_modified")+LLTrans::getString("never_text");
- }
- else
- {
- last_modified = LLTrans::getString("covenant_last_modified")+"["
- +LLTrans::getString("LTimeWeek")+"] ["
- +LLTrans::getString("LTimeMonth")+"] ["
- +LLTrans::getString("LTimeDay")+"] ["
- +LLTrans::getString("LTimeHour")+"]:["
- +LLTrans::getString("LTimeMin")+"]:["
- +LLTrans::getString("LTimeSec")+"] ["
- +LLTrans::getString("LTimeYear")+"]";
- LLSD substitution;
- substitution["datetime"] = (S32) covenant_timestamp;
- LLStringUtil::format (last_modified, substitution);
- }
-
- LLPanelEstateCovenant::updateLastModified(last_modified);
- LLPanelLandCovenant::updateLastModified(last_modified);
- LLFloaterBuyLand::updateLastModified(last_modified);
-
- // load the actual covenant asset data
- const BOOL high_priority = TRUE;
- if (covenant_id.notNull())
- {
- gAssetStorage->getEstateAsset(gAgent.getRegionHost(),
- gAgent.getID(),
- gAgent.getSessionID(),
- covenant_id,
- LLAssetType::AT_NOTECARD,
- ET_Covenant,
- onCovenantLoadComplete,
- NULL,
- high_priority);
- }
- else
- {
- std::string covenant_text;
- if (estate_owner_id.isNull())
- {
- // mainland
- covenant_text = LLTrans::getString("RegionNoCovenant");
- }
- else
- {
- covenant_text = LLTrans::getString("RegionNoCovenantOtherOwner");
- }
- LLPanelEstateCovenant::updateCovenantText(covenant_text, covenant_id);
- LLPanelLandCovenant::updateCovenantText(covenant_text);
- LLFloaterBuyLand::updateCovenantText(covenant_text, covenant_id);
- if (panel)
- {
- panel->updateCovenantText(covenant_text);
- }
- }
-}
-
-void onCovenantLoadComplete(LLVFS *vfs,
- const LLUUID& asset_uuid,
- LLAssetType::EType type,
- void* user_data, S32 status, LLExtStat ext_status)
-{
- LL_DEBUGS("Messaging") << "onCovenantLoadComplete()" << LL_ENDL;
- std::string covenant_text;
- if(0 == status)
- {
- LLVFile file(vfs, asset_uuid, type, LLVFile::READ);
-
- S32 file_length = file.getSize();
-
- std::vector<char> buffer(file_length+1);
- file.read((U8*)&buffer[0], file_length);
- // put a EOS at the end
- buffer[file_length] = '\0';
-
- if( (file_length > 19) && !strncmp( &buffer[0], "Linden text version", 19 ) )
- {
- LLViewerTextEditor::Params params;
- params.name("temp");
- params.max_text_length(file_length+1);
- LLViewerTextEditor * editor = LLUICtrlFactory::create<LLViewerTextEditor> (params);
- if( !editor->importBuffer( &buffer[0], file_length+1 ) )
- {
- LL_WARNS("Messaging") << "Problem importing estate covenant." << LL_ENDL;
- covenant_text = "Problem importing estate covenant.";
- }
- else
- {
- // Version 0 (just text, doesn't include version number)
- covenant_text = editor->getText();
- }
- delete editor;
- }
- else
- {
- LL_WARNS("Messaging") << "Problem importing estate covenant: Covenant file format error." << LL_ENDL;
- covenant_text = "Problem importing estate covenant: Covenant file format error.";
- }
- }
- else
- {
- LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
-
- if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
- LL_ERR_FILE_EMPTY == status)
- {
- covenant_text = "Estate covenant notecard is missing from database.";
- }
- else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
- {
- covenant_text = "Insufficient permissions to view estate covenant.";
- }
- else
- {
- covenant_text = "Unable to load estate covenant at this time.";
- }
-
- LL_WARNS("Messaging") << "Problem loading notecard: " << status << LL_ENDL;
- }
- LLPanelEstateCovenant::updateCovenantText(covenant_text, asset_uuid);
- LLPanelLandCovenant::updateCovenantText(covenant_text);
- LLFloaterBuyLand::updateCovenantText(covenant_text, asset_uuid);
-
- LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info");
- if (panel)
- {
- panel->updateCovenantText(covenant_text);
- }
-}
-
-
-void process_feature_disabled_message(LLMessageSystem* msg, void**)
-{
- // Handle Blacklisted feature simulator response...
- LLUUID agentID;
- LLUUID transactionID;
- std::string messageText;
- msg->getStringFast(_PREHASH_FailureInfo,_PREHASH_ErrorMessage, messageText,0);
- msg->getUUIDFast(_PREHASH_FailureInfo,_PREHASH_AgentID,agentID);
- msg->getUUIDFast(_PREHASH_FailureInfo,_PREHASH_TransactionID,transactionID);
-
- LL_WARNS("Messaging") << "Blacklisted Feature Response:" << messageText << LL_ENDL;
-}
-
-// ------------------------------------------------------------
-// Message system exception callbacks
-// ------------------------------------------------------------
-
-void invalid_message_callback(LLMessageSystem* msg,
- void*,
- EMessageException exception)
-{
- LLAppViewer::instance()->badNetworkHandler();
-}
-
-// Please do not add more message handlers here. This file is huge.
-// Put them in a file related to the functionality you are implementing.
-
-void LLOfferInfo::forceResponse(InventoryOfferResponse response)
-{
- LLNotification::Params params("UserGiveItem");
- params.functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, this, _1, _2));
- LLNotifications::instance().forceResponse(params, response);
-}
+/** + * @file llviewermessage.cpp + * @brief Dumping ground for viewer-side message system callbacks. + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-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 "llviewermessage.h" + +#include <deque> + +#include "llaudioengine.h" +#include "indra_constants.h" +#include "lscript_byteformat.h" +#include "mean_collision_data.h" +#include "llfloaterbump.h" +#include "llassetstorage.h" +#include "llcachename.h" +#include "llchat.h" +#include "lldbstrings.h" +#include "lleconomy.h" +#include "llfilepicker.h" +#include "llfloaterreg.h" +#include "llfocusmgr.h" +#include "llfollowcamparams.h" +#include "llinstantmessage.h" +#include "llquantize.h" +#include "llregionflags.h" +#include "llregionhandle.h" +#include "llsdserialize.h" +#include "llstring.h" +#include "llteleportflags.h" +#include "lltracker.h" +#include "lltransactionflags.h" +#include "llxfermanager.h" +#include "message.h" +#include "sound_ids.h" +#include "lltimer.h" +#include "llmd5.h" + +#include "llagent.h" +#include "llcallingcard.h" +#include "llconsole.h" +#include "llvieweraudio.h" +#include "llviewercontrol.h" +#include "lldrawpool.h" +#include "llfirstuse.h" +#include "llfloateranimpreview.h" +#include "llfloaterbuycurrency.h" +#include "llfloaterbuyland.h" +#include "llfloaterchat.h" +#include "llfloaterimagepreview.h" +#include "llfloaterland.h" +#include "llfloaterregioninfo.h" +#include "llfloaterlandholdings.h" +#include "llurldispatcher.h" +#include "llfloaterpostcard.h" +#include "llfloaterpreference.h" +#include "llfollowcam.h" +#include "llgroupnotify.h" +#include "llhudeffect.h" +#include "llhudeffecttrail.h" +#include "llhudmanager.h" +#include "llinventorymodel.h" +#include "llinventorypanel.h" +#include "llfloaterinventory.h" +#include "llmenugl.h" +#include "llmoveview.h" +#include "llmutelist.h" +#include "llnearbychat.h" +#include "llnotifications.h" +#include "llnotify.h" +#include "llpanelgrouplandmoney.h" +#include "llpanelplaces.h" +#include "llrecentpeople.h" +#include "llselectmgr.h" +#include "llsidetray.h" +#include "llstartup.h" +#include "llsky.h" +#include "llslurl.h" +#include "llstatenums.h" +#include "llstatusbar.h" +#include "llimview.h" +#include "lltool.h" +#include "lltoolbar.h" +#include "lltoolmgr.h" +#include "lltrans.h" +#include "llui.h" // for make_ui_sound +#include "lluploaddialog.h" +#include "llviewercamera.h" +#include "llviewergenericmessage.h" +#include "llviewerinventory.h" +#include "llviewermenu.h" +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "llviewerparcelmgr.h" +#include "llviewerpartsource.h" +#include "llviewerregion.h" +#include "llviewerstats.h" +#include "llviewertexteditor.h" +#include "llviewerthrottle.h" +#include "llviewerwindow.h" +#include "llvlmanager.h" +#include "llvoavatarself.h" +#include "llvotextbubble.h" +#include "llweb.h" +#include "llworld.h" +#include "pipeline.h" +#include "llappviewer.h" +#include "llfloaterworldmap.h" +#include "llviewerdisplay.h" +#include "llkeythrottle.h" +#include "llgroupactions.h" +#include "llagentui.h" +#include "llpanelblockedlist.h" +#include "llpanelplaceinfo.h" + +#include <boost/tokenizer.hpp> +#include <boost/algorithm/string/split.hpp> + +#if LL_WINDOWS // For Windows specific error handler +#include "llwindebug.h" // For the invalid message handler +#endif + +//#include "llnearbychathistory.h" +#include "llnotificationmanager.h" + +// +// Constants +// +const F32 BIRD_AUDIBLE_RADIUS = 32.0f; +const F32 SIT_DISTANCE_FROM_TARGET = 0.25f; +static const F32 LOGOUT_REPLY_TIME = 3.f; // Wait this long after LogoutReply before quitting. + +// Determine how quickly residents' scripts can issue question dialogs +// Allow bursts of up to 5 dialogs in 10 seconds. 10*2=20 seconds recovery if throttle kicks in +static const U32 LLREQUEST_PERMISSION_THROTTLE_LIMIT = 5; // requests +static const F32 LLREQUEST_PERMISSION_THROTTLE_INTERVAL = 10.0f; // seconds + +extern BOOL gDebugClicks; + +// function prototypes +void open_offer(const std::vector<LLUUID>& items, const std::string& from_name); +bool check_offer_throttle(const std::string& from_name, bool check_only); + +//inventory offer throttle globals +LLFrameTimer gThrottleTimer; +const U32 OFFER_THROTTLE_MAX_COUNT=5; //number of items per time period +const F32 OFFER_THROTTLE_TIME=10.f; //time period in seconds + +//script permissions +const std::string SCRIPT_QUESTIONS[SCRIPT_PERMISSION_EOF] = + { + "ScriptTakeMoney", + "ActOnControlInputs", + "RemapControlInputs", + "AnimateYourAvatar", + "AttachToYourAvatar", + "ReleaseOwnership", + "LinkAndDelink", + "AddAndRemoveJoints", + "ChangePermissions", + "TrackYourCamera", + "ControlYourCamera" + }; + +const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = +{ + TRUE, // ScriptTakeMoney, + FALSE, // ActOnControlInputs + FALSE, // RemapControlInputs + FALSE, // AnimateYourAvatar + FALSE, // AttachToYourAvatar + FALSE, // ReleaseOwnership, + FALSE, // LinkAndDelink, + FALSE, // AddAndRemoveJoints + FALSE, // ChangePermissions + FALSE, // TrackYourCamera, + FALSE // ControlYourCamera +}; + +bool friendship_offer_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + LLUUID fid; + LLMessageSystem* msg = gMessageSystem; + const LLSD& payload = notification["payload"]; + + // add friend to recent people list + LLRecentPeople::instance().add(payload["from_id"]); + + switch(option) + { + case 0: + // accept + LLAvatarTracker::formFriendship(payload["from_id"]); + + fid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + + // This will also trigger an onlinenotification if the user is online + msg->newMessageFast(_PREHASH_AcceptFriendship); + 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->nextBlockFast(_PREHASH_FolderData); + msg->addUUIDFast(_PREHASH_FolderID, fid); + 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; + default: + // close button probably, possibly timed out + break; + } + + return false; +} +static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback); +static LLNotificationFunctorRegistration friendship_offer_callback_reg_nm("OfferFriendshipNoMessage", friendship_offer_callback); + +//const char BUSY_AUTO_RESPONSE[] = "The Resident you messaged is in 'busy mode' which means they have " +// "requested not to be disturbed. Your message will still be shown in their IM " +// "panel for later viewing."; + +// +// Functions +// + +void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_group, + S32 trx_type, const std::string& desc) +{ + if(0 == amount || !region) return; + amount = abs(amount); + LL_INFOS("Messaging") << "give_money(" << uuid << "," << amount << ")"<< LL_ENDL; + if(can_afford_transaction(amount)) + { +// gStatusBar->debitBalance(amount); + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_MoneyTransferRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_MoneyData); + msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_DestID, uuid); + msg->addU8Fast(_PREHASH_Flags, pack_transaction_flags(FALSE, is_group)); + msg->addS32Fast(_PREHASH_Amount, amount); + msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY); + msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY); + msg->addS32Fast(_PREHASH_TransactionType, trx_type ); + msg->addStringFast(_PREHASH_Description, desc); + msg->sendReliable(region->getHost()); + } + else + { + LLFloaterBuyCurrency::buyCurrency("Giving", amount); + } +} + +void send_complete_agent_movement(const LLHost& sim_host) +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_CompleteAgentMovement); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addU32Fast(_PREHASH_CircuitCode, msg->mOurCircuitCode); + msg->sendReliable(sim_host); +} + +void process_logout_reply(LLMessageSystem* msg, void**) +{ + // The server has told us it's ok to quit. + LL_DEBUGS("Messaging") << "process_logout_reply" << LL_ENDL; + + LLUUID agent_id; + msg->getUUID("AgentData", "AgentID", agent_id); + LLUUID session_id; + msg->getUUID("AgentData", "SessionID", session_id); + if((agent_id != gAgent.getID()) || (session_id != gAgent.getSessionID())) + { + LL_WARNS("Messaging") << "Bogus Logout Reply" << LL_ENDL; + } + + LLInventoryModel::update_map_t parents; + S32 count = msg->getNumberOfBlocksFast( _PREHASH_InventoryData ); + for(S32 i = 0; i < count; ++i) + { + LLUUID item_id; + msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id, i); + + if( (1 == count) && item_id.isNull() ) + { + // Detect dummy item. Indicates an empty list. + break; + } + + // We do not need to track the asset ids, just account for an + // updated inventory version. + LL_INFOS("Messaging") << "process_logout_reply itemID=" << item_id << LL_ENDL; + LLInventoryItem* item = gInventory.getItem( item_id ); + if( item ) + { + parents[item->getParentUUID()] = 0; + gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item_id); + } + else + { + LL_INFOS("Messaging") << "process_logout_reply item not found: " << item_id << LL_ENDL; + } + } + LLAppViewer::instance()->forceQuit(); +} + +void process_layer_data(LLMessageSystem *mesgsys, void **user_data) +{ + LLViewerRegion *regionp = LLWorld::getInstance()->getRegion(mesgsys->getSender()); + + if (!regionp || gNoRender) + { + return; + } + + + S32 size; + S8 type; + + mesgsys->getS8Fast(_PREHASH_LayerID, _PREHASH_Type, type); + size = mesgsys->getSizeFast(_PREHASH_LayerData, _PREHASH_Data); + if (0 == size) + { + LL_WARNS("Messaging") << "Layer data has zero size." << LL_ENDL; + return; + } + if (size < 0) + { + // getSizeFast() is probably trying to tell us about an error + LL_WARNS("Messaging") << "getSizeFast() returned negative result: " + << size + << LL_ENDL; + return; + } + U8 *datap = new U8[size]; + mesgsys->getBinaryDataFast(_PREHASH_LayerData, _PREHASH_Data, datap, size); + LLVLData *vl_datap = new LLVLData(regionp, type, datap, size); + if (mesgsys->getReceiveCompressedSize()) + { + gVLManager.addLayerData(vl_datap, mesgsys->getReceiveCompressedSize()); + } + else + { + gVLManager.addLayerData(vl_datap, mesgsys->getReceiveSize()); + } +} + +// S32 exported_object_count = 0; +// S32 exported_image_count = 0; +// S32 current_object_count = 0; +// S32 current_image_count = 0; + +// extern LLNotifyBox *gExporterNotify; +// extern LLUUID gExporterRequestID; +// extern std::string gExportDirectory; + +// extern LLUploadDialog *gExportDialog; + +// std::string gExportedFile; + +// std::map<LLUUID, std::string> gImageChecksums; + +// void export_complete() +// { +// LLUploadDialog::modalUploadFinished(); +// gExporterRequestID.setNull(); +// gExportDirectory = ""; + +// LLFILE* fXML = LLFile::fopen(gExportedFile, "rb"); /* Flawfinder: ignore */ +// fseek(fXML, 0, SEEK_END); +// long length = ftell(fXML); +// fseek(fXML, 0, SEEK_SET); +// U8 *buffer = new U8[length + 1]; +// size_t nread = fread(buffer, 1, length, fXML); +// if (nread < (size_t) length) +// { +// LL_WARNS("Messaging") << "Short read" << LL_ENDL; +// } +// buffer[nread] = '\0'; +// fclose(fXML); + +// char *pos = (char *)buffer; +// while ((pos = strstr(pos+1, "<sl:image ")) != 0) +// { +// char *pos_check = strstr(pos, "checksum=\""); + +// if (pos_check) +// { +// char *pos_uuid = strstr(pos_check, "\">"); + +// if (pos_uuid) +// { +// char image_uuid_str[UUID_STR_SIZE]; /* Flawfinder: ignore */ +// memcpy(image_uuid_str, pos_uuid+2, UUID_STR_SIZE-1); /* Flawfinder: ignore */ +// image_uuid_str[UUID_STR_SIZE-1] = 0; + +// LLUUID image_uuid(image_uuid_str); + +// LL_INFOS("Messaging") << "Found UUID: " << image_uuid << LL_ENDL; + +// std::map<LLUUID, std::string>::iterator itor = gImageChecksums.find(image_uuid); +// if (itor != gImageChecksums.end()) +// { +// LL_INFOS("Messaging") << "Replacing with checksum: " << itor->second << LL_ENDL; +// if (!itor->second.empty()) +// { +// memcpy(&pos_check[10], itor->second.c_str(), 32); /* Flawfinder: ignore */ +// } +// } +// } +// } +// } + +// LLFILE* fXMLOut = LLFile::fopen(gExportedFile, "wb"); /* Flawfinder: ignore */ +// if (fwrite(buffer, 1, length, fXMLOut) != length) +// { +// LL_WARNS("Messaging") << "Short write" << LL_ENDL; +// } +// fclose(fXMLOut); + +// delete [] buffer; +// } + + +// void exported_item_complete(const LLTSCode status, void *user_data) +// { +// //std::string *filename = (std::string *)user_data; + +// if (status < LLTS_OK) +// { +// LL_WARNS("Messaging") << "Export failed!" << LL_ENDL; +// } +// else +// { +// ++current_object_count; +// if (current_image_count == exported_image_count && current_object_count == exported_object_count) +// { +// LL_INFOS("Messaging") << "*** Export complete ***" << LL_ENDL; + +// export_complete(); +// } +// else +// { +// gExportDialog->setMessage(llformat("Exported %d/%d object files, %d/%d textures.", current_object_count, exported_object_count, current_image_count, exported_image_count)); +// } +// } +// } + +// struct exported_image_info +// { +// LLUUID image_id; +// std::string filename; +// U32 image_num; +// }; + +// void exported_j2c_complete(const LLTSCode status, void *user_data) +// { +// exported_image_info *info = (exported_image_info *)user_data; +// LLUUID image_id = info->image_id; +// U32 image_num = info->image_num; +// std::string filename = info->filename; +// delete info; + +// if (status < LLTS_OK) +// { +// LL_WARNS("Messaging") << "Image download failed!" << LL_ENDL; +// } +// else +// { +// LLFILE* fIn = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ +// if (fIn) +// { +// LLPointer<LLImageJ2C> ImageUtility = new LLImageJ2C; +// LLPointer<LLImageTGA> TargaUtility = new LLImageTGA; + +// fseek(fIn, 0, SEEK_END); +// S32 length = ftell(fIn); +// fseek(fIn, 0, SEEK_SET); +// U8 *buffer = ImageUtility->allocateData(length); +// if (fread(buffer, 1, length, fIn) != length) +// { +// LL_WARNS("Messaging") << "Short read" << LL_ENDL; +// } +// fclose(fIn); +// LLFile::remove(filename); + +// // Convert to TGA +// LLPointer<LLImageRaw> image = new LLImageRaw(); + +// ImageUtility->updateData(); +// ImageUtility->decode(image, 100000.0f); + +// TargaUtility->encode(image); +// U8 *data = TargaUtility->getData(); +// S32 data_size = TargaUtility->getDataSize(); + +// std::string file_path = gDirUtilp->getDirName(filename); + +// std::string output_file = llformat("%s/image-%03d.tga", file_path.c_str(), image_num);//filename; +// //S32 name_len = output_file.length(); +// //strcpy(&output_file[name_len-3], "tga"); +// LLFILE* fOut = LLFile::fopen(output_file, "wb"); /* Flawfinder: ignore */ +// char md5_hash_string[33]; /* Flawfinder: ignore */ +// strcpy(md5_hash_string, "00000000000000000000000000000000"); /* Flawfinder: ignore */ +// if (fOut) +// { +// if (fwrite(data, 1, data_size, fOut) != data_size) +// { +// LL_WARNS("Messaging") << "Short write" << LL_ENDL; +// } +// fseek(fOut, 0, SEEK_SET); +// fclose(fOut); +// fOut = LLFile::fopen(output_file, "rb"); /* Flawfinder: ignore */ +// LLMD5 my_md5_hash(fOut); +// my_md5_hash.hex_digest(md5_hash_string); +// } + +// gImageChecksums.insert(std::pair<LLUUID, std::string>(image_id, md5_hash_string)); +// } +// } + +// ++current_image_count; +// if (current_image_count == exported_image_count && current_object_count == exported_object_count) +// { +// LL_INFOS("Messaging") << "*** Export textures complete ***" << LL_ENDL; +// export_complete(); +// } +// else +// { +// gExportDialog->setMessage(llformat("Exported %d/%d object files, %d/%d textures.", current_object_count, exported_object_count, current_image_count, exported_image_count)); +// } +//} + +void process_derez_ack(LLMessageSystem*, void**) +{ + if(gViewerWindow) gViewerWindow->getWindow()->decBusyCount(); +} + +void process_places_reply(LLMessageSystem* msg, void** data) +{ + LLUUID query_id; + + msg->getUUID("AgentData", "QueryID", query_id); + if (query_id.isNull()) + { + LLFloaterLandHoldings::processPlacesReply(msg, data); + } + else if(gAgent.isInGroup(query_id)) + { + LLPanelGroupLandMoney::processPlacesReply(msg, data); + } + else + { + LL_WARNS("Messaging") << "Got invalid PlacesReply message" << LL_ENDL; + } +} + +void send_sound_trigger(const LLUUID& sound_id, F32 gain) +{ + if (sound_id.isNull() || gAgent.getRegion() == NULL) + { + // disconnected agent or zero guids don't get sent (no sound) + return; + } + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_SoundTrigger); + msg->nextBlockFast(_PREHASH_SoundData); + msg->addUUIDFast(_PREHASH_SoundID, sound_id); + // Client untrusted, ids set on sim + msg->addUUIDFast(_PREHASH_OwnerID, LLUUID::null ); + msg->addUUIDFast(_PREHASH_ObjectID, LLUUID::null ); + msg->addUUIDFast(_PREHASH_ParentID, LLUUID::null ); + + msg->addU64Fast(_PREHASH_Handle, gAgent.getRegion()->getHandle()); + + LLVector3 position = gAgent.getPositionAgent(); + msg->addVector3Fast(_PREHASH_Position, position); + msg->addF32Fast(_PREHASH_Gain, gain); + + gAgent.sendMessage(); +} + +bool join_group_response(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + BOOL delete_context_data = TRUE; + bool accept_invite = false; + + LLUUID group_id = notification["payload"]["group_id"].asUUID(); + LLUUID transaction_id = notification["payload"]["transaction_id"].asUUID(); + std::string name = notification["payload"]["name"].asString(); + std::string message = notification["payload"]["message"].asString(); + S32 fee = notification["payload"]["fee"].asInteger(); + + if (option == 2 && !group_id.isNull()) + { + LLGroupActions::show(group_id); + LLSD args; + args["MESSAGE"] = message; + LLNotifications::instance().add("JoinGroup", args, notification["payload"]); + return false; + } + if(option == 0 && !group_id.isNull()) + { + // check for promotion or demotion. + S32 max_groups = MAX_AGENT_GROUPS; + if(gAgent.isInGroup(group_id)) ++max_groups; + + if(gAgent.mGroups.count() < max_groups) + { + accept_invite = true; + } + else + { + delete_context_data = FALSE; + LLSD args; + args["NAME"] = name; + args["INVITE"] = message; + LLNotifications::instance().add("JoinedTooManyGroupsMember", args, notification["payload"]); + } + } + + if (accept_invite) + { + // If there is a fee to join this group, make + // sure the user is sure they want to join. + if (fee > 0) + { + delete_context_data = FALSE; + LLSD args; + args["COST"] = llformat("%d", fee); + // Set the fee for next time to 0, so that we don't keep + // asking about a fee. + LLSD next_payload = notification["payload"]; + next_payload["fee"] = 0; + LLNotifications::instance().add("JoinGroupCanAfford", + args, + next_payload); + } + else + { + send_improved_im(group_id, + std::string("name"), + std::string("message"), + IM_ONLINE, + IM_GROUP_INVITATION_ACCEPT, + transaction_id); + } + } + else + { + send_improved_im(group_id, + std::string("name"), + std::string("message"), + IM_ONLINE, + IM_GROUP_INVITATION_DECLINE, + transaction_id); + } + + return false; +} +static LLNotificationFunctorRegistration jgr_1("JoinGroup", join_group_response); +static LLNotificationFunctorRegistration jgr_2("JoinedTooManyGroupsMember", join_group_response); +static LLNotificationFunctorRegistration jgr_3("JoinGroupCanAfford", join_group_response); + + +//----------------------------------------------------------------------------- +// Instant Message +//----------------------------------------------------------------------------- +class LLOpenAgentOffer : public LLInventoryFetchObserver +{ +public: + LLOpenAgentOffer(const std::string& from_name) : mFromName(from_name) {} + /*virtual*/ void done() + { + open_offer(mComplete, mFromName); + gInventory.removeObserver(this); + delete this; + } +private: + std::string mFromName; +}; + +//unlike the FetchObserver for AgentOffer, we only make one +//instance of the AddedObserver for TaskOffers +//and it never dies. We do this because we don't know the UUID of +//task offers until they are accepted, so we don't wouldn't +//know what to watch for, so instead we just watch for all additions. +class LLOpenTaskOffer : public LLInventoryAddedObserver +{ +protected: + /*virtual*/ void done() + { + open_offer(mAdded, ""); + mAdded.clear(); + } + }; + +//one global instance to bind them +LLOpenTaskOffer* gNewInventoryObserver=NULL; + +void start_new_inventory_observer() +{ + if (!gNewInventoryObserver) //task offer observer + { + // Observer is deleted by gInventory + gNewInventoryObserver = new LLOpenTaskOffer; + gInventory.addObserver(gNewInventoryObserver); + } +} + +class LLDiscardAgentOffer : public LLInventoryFetchComboObserver +{ +public: + LLDiscardAgentOffer(const LLUUID& folder_id, const LLUUID& object_id) : + mFolderID(folder_id), + mObjectID(object_id) {} + virtual ~LLDiscardAgentOffer() {} + virtual void done() + { + LL_DEBUGS("Messaging") << "LLDiscardAgentOffer::done()" << LL_ENDL; + LLUUID trash_id; + trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + bool notify = false; + if(trash_id.notNull() && mObjectID.notNull()) + { + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(mFolderID, -1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1); + update.push_back(new_folder); + gInventory.accountForUpdate(update); + gInventory.moveObject(mObjectID, trash_id); + LLInventoryObject* obj = gInventory.getObject(mObjectID); + if(obj) + { + // no need to restamp since this is already a freshly + // stamped item. + obj->updateParentOnServer(FALSE); + notify = true; + } + } + else + { + LL_WARNS("Messaging") << "DiscardAgentOffer unable to find: " + << (trash_id.isNull() ? "trash " : "") + << (mObjectID.isNull() ? "object" : "") << LL_ENDL; + } + gInventory.removeObserver(this); + if(notify) + { + gInventory.notifyObservers(); + } + delete this; + } +protected: + LLUUID mFolderID; + LLUUID mObjectID; +}; + + +//Returns TRUE if we are OK, FALSE if we are throttled +//Set check_only true if you want to know the throttle status +//without registering a hit +bool check_offer_throttle(const std::string& from_name, bool check_only) +{ + static U32 throttle_count; + static bool throttle_logged; + LLChat chat; + std::string log_message; + + if (!gSavedSettings.getBOOL("ShowNewInventory")) + return false; + + if (check_only) + { + return gThrottleTimer.hasExpired(); + } + + if(gThrottleTimer.checkExpirationAndReset(OFFER_THROTTLE_TIME)) + { + LL_DEBUGS("Messaging") << "Throttle Expired" << LL_ENDL; + throttle_count=1; + throttle_logged=false; + return true; + } + else //has not expired + { + LL_DEBUGS("Messaging") << "Throttle Not Expired, Count: " << throttle_count << LL_ENDL; + // When downloading the initial inventory we get a lot of new items + // coming in and can't tell that from spam. + if (LLStartUp::getStartupState() >= STATE_STARTED + && throttle_count >= OFFER_THROTTLE_MAX_COUNT) + { + if (!throttle_logged) + { + // Use the name of the last item giver, who is probably the person + // spamming you. + std::ostringstream message; + message << LLAppViewer::instance()->getSecondLifeTitle(); + if (!from_name.empty()) + { + message << ": Items coming in too fast from " << from_name; + } + else + { + message << ": Items coming in too fast"; + } + message << ", automatic preview disabled for " + << OFFER_THROTTLE_TIME << " seconds."; + chat.mText = message.str(); + //this is kinda important, so actually put it on screen + LLFloaterChat::addChat(chat, FALSE, FALSE); + throttle_logged=true; + } + return false; + } + else + { + throttle_count++; + return true; + } + } +} + +void open_offer(const std::vector<LLUUID>& items, const std::string& from_name) +{ + std::vector<LLUUID>::const_iterator it = items.begin(); + std::vector<LLUUID>::const_iterator end = items.end(); + LLUUID trash_id(gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH)); + LLInventoryItem* item; + for(; it != end; ++it) + { + const LLUUID& id = *it; + item = gInventory.getItem(id); + if(!item) + { + LL_WARNS("Messaging") << "Unable to show inventory item: " << id << LL_ENDL; + continue; + } + if(gInventory.isObjectDescendentOf(id, trash_id)) + { + continue; + } + LLAssetType::EType asset_type = item->getType(); + + //if we are throttled, don't display them + if (check_offer_throttle(from_name, false)) + { + // If we opened this ourselves, focus it + BOOL take_focus = from_name.empty() ? TAKE_FOCUS_YES : TAKE_FOCUS_NO; + switch(asset_type) + { + case LLAssetType::AT_NOTECARD: + LLFloaterReg::showInstance("preview_notecard", LLSD(id), take_focus); + break; + case LLAssetType::AT_LANDMARK: + { + LLInventoryCategory* parent_folder = gInventory.getCategory(item->getParentUUID()); + LLSD args; + args["LANDMARK_NAME"] = item->getName(); + args["FOLDER_NAME"] = std::string(parent_folder ? parent_folder->getName() : "unknown"); + LLNotifications::instance().add("LandmarkCreated", args); + + // Created landmark is passed to Places panel to allow its editing. + LLPanelPlaces *panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->showPanel("panel_places", LLSD())); + if (panel) + { + panel->setItem(item); + } + } + break; + case LLAssetType::AT_TEXTURE: + LLFloaterReg::showInstance("preview_texture", LLSD(id), take_focus); + break; + default: + break; + } + } + //highlight item, if it's not in the trash or lost+found + + // Don't auto-open the inventory floater + LLFloaterInventory* view = NULL; + if(gSavedSettings.getBOOL("ShowInInventory") && + asset_type != LLAssetType::AT_CALLINGCARD && + item->getInventoryType() != LLInventoryType::IT_ATTACHMENT && + !from_name.empty()) + { + view = LLFloaterInventory::showAgentInventory(); + } + else + { + view = LLFloaterInventory::getActiveInventory(); + } + if(!view) + { + return; + } + + //Trash Check + LLUUID trash_id; + trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) + { + return; + } + LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + //BOOL inventory_has_focus = gFocusMgr.childHasKeyboardFocus(view); + BOOL user_is_away = gAwayTimer.getStarted(); + + // don't select lost and found items if the user is active + if (gInventory.isObjectDescendentOf(item->getUUID(), lost_and_found_id) + && !user_is_away) + { + return; + } + + //Not sure about this check. Could make it easy to miss incoming items. + //don't dick with highlight while the user is working + //if(inventory_has_focus && !user_is_away) + // break; + LL_DEBUGS("Messaging") << "Highlighting" << item->getUUID() << LL_ENDL; + //highlight item + + if (view->getPanel()) + { + LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus(); + view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO); + gFocusMgr.setKeyboardFocus(focus_ctrl); + } + } +} + +void inventory_offer_mute_callback(const LLUUID& blocked_id, + const std::string& first_name, + const std::string& last_name, + BOOL is_group) +{ + std::string from_name; + LLMute::EType type; + + if (is_group) + { + type = LLMute::GROUP; + from_name = first_name; + } + else + { + type = LLMute::AGENT; + from_name = first_name + " " + last_name; + } + + LLMute mute(blocked_id, from_name, type); + if (LLMuteList::getInstance()->add(mute)) + { + LLPanelBlockedList::showPanelAndSelect(blocked_id); + } + + // purge the message queue of any previously queued inventory offers from the same source. + class OfferMatcher : public LLNotifyBoxView::Matcher + { + public: + OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {} + BOOL matches(const LLNotificationPtr notification) const + { + if(notification->getName() == "ObjectGiveItem" + || notification->getName() == "ObjectGiveItemUnknownUser" + || notification->getName() == "UserGiveItem") + { + return (notification->getPayload()["from_id"].asUUID() == blocked_id); + } + return FALSE; + } + private: + const LLUUID& blocked_id; + }; + gNotifyBoxView->purgeMessagesMatching(OfferMatcher(blocked_id)); +} + +LLOfferInfo::LLOfferInfo(const LLSD& sd) +{ + mIM = (EInstantMessage)sd["im_type"].asInteger(); + mFromID = sd["from_id"].asUUID(); + mFromGroup = sd["from_group"].asBoolean(); + mFromObject = sd["from_object"].asBoolean(); + mTransactionID = sd["transaction_id"].asUUID(); + mFolderID = sd["folder_id"].asUUID(); + mObjectID = sd["object_id"].asUUID(); + mType = LLAssetType::lookup(sd["type"].asString().c_str()); + mFromName = sd["from_name"].asString(); + mDesc = sd["description"].asString(); + mHost = LLHost(sd["sender"].asString()); +} + +LLSD LLOfferInfo::asLLSD() +{ + LLSD sd; + sd["im_type"] = mIM; + sd["from_id"] = mFromID; + sd["from_group"] = mFromGroup; + sd["from_object"] = mFromObject; + sd["transaction_id"] = mTransactionID; + sd["folder_id"] = mFolderID; + sd["object_id"] = mObjectID; + sd["type"] = LLAssetType::lookup(mType); + sd["from_name"] = mFromName; + sd["description"] = mDesc; + sd["sender"] = mHost.getIPandPort(); + return sd; +} + +bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& response) + { + LLChat chat; + std::string log_message; + S32 button = LLNotification::getSelectedOption(notification, response); + + // For muting, we need to add the mute, then decline the offer. + // This must be done here because: + // * callback may be called immediately, + // * adding the mute sends a message, + // * we can't build two messages at once. + if (2 == button) + { + gCacheName->get(mFromID, mFromGroup, &inventory_offer_mute_callback); + } + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ImprovedInstantMessage); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_MessageBlock); + msg->addBOOLFast(_PREHASH_FromGroup, FALSE); + msg->addUUIDFast(_PREHASH_ToAgentID, mFromID); + msg->addU8Fast(_PREHASH_Offline, IM_ONLINE); + msg->addUUIDFast(_PREHASH_ID, mTransactionID); + msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary + std::string name; + LLAgentUI::buildFullname(name); + msg->addStringFast(_PREHASH_FromAgentName, name); + msg->addStringFast(_PREHASH_Message, ""); + msg->addU32Fast(_PREHASH_ParentEstateID, 0); + msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null); + msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); + LLInventoryObserver* opener = NULL; + LLViewerInventoryCategory* catp = NULL; + catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID); + LLViewerInventoryItem* itemp = NULL; + if(!catp) + { + itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID); + } + + std::string from_string; // Used in the pop-up. + std::string chatHistory_string; // Used in chat history. + if (mFromObject == TRUE) + { + if (mFromGroup) + { + std::string group_name; + if (gCacheName->getGroupName(mFromID, group_name)) + { + from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'" + + mFromName + LLTrans::getString("'") +" " + LLTrans::getString("InvOfferOwnedByGroup") + + " "+ "'" + group_name + "'"; + + chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByGroup") + + " " + group_name + "'"; + } + else + { + from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'" + + mFromName +"'"+ " " + LLTrans::getString("InvOfferOwnedByUnknownGroup"); + chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownGroup"); + } + } + else + { + std::string first_name, last_name; + if (gCacheName->getName(mFromID, first_name, last_name)) + { + from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+ LLTrans::getString("'") + mFromName + + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedBy") + first_name + " " + last_name; + chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedBy") + " " + first_name + " " + last_name; + } + else + { + from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+LLTrans::getString("'") + + mFromName + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedByUnknownUser"); + chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownUser"); + } + } + } + else + { + from_string = chatHistory_string = mFromName; + } + + bool busy=FALSE; + + switch(button) + { + case IOR_ACCEPT: + // ACCEPT. The math for the dialog works, because the accept + // for inventory_offered, task_inventory_offer or + // group_notice_inventory is 1 greater than the offer integer value. + // Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED, + // or IM_GROUP_NOTICE_INVENTORY_ACCEPTED + msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1)); + msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData), + sizeof(mFolderID.mData)); + // send the message + msg->sendReliable(mHost); + + //don't spam them if they are getting flooded + if (check_offer_throttle(mFromName, true)) + { + log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString("."); + chat.mText = log_message; + LLFloaterChat::addChatHistory(chat); + } + + // we will want to open this item when it comes back. + LL_DEBUGS("Messaging") << "Initializing an opener for tid: " << mTransactionID + << LL_ENDL; + switch (mIM) + { + case IM_INVENTORY_OFFERED: + { + // This is an offer from an agent. In this case, the back + // end has already copied the items into your inventory, + // so we can fetch it out of our inventory. + LLInventoryFetchObserver::item_ref_t items; + items.push_back(mObjectID); + LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(from_string); + open_agent_offer->fetchItems(items); + if(catp || (itemp && itemp->isComplete())) + { + open_agent_offer->done(); + } + else + { + opener = open_agent_offer; + } + } + break; + case IM_TASK_INVENTORY_OFFERED: + case IM_GROUP_NOTICE: + case IM_GROUP_NOTICE_REQUESTED: + { + // This is an offer from a task or group. + // We don't use a new instance of an opener + // We instead use the singular observer gOpenTaskOffer + // Since it already exists, we don't need to actually do anything + } + break; + default: + LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL; + break; + } // end switch (mIM) + break; + + case IOR_BUSY: + //Busy falls through to decline. Says to make busy message. + busy=TRUE; + case IOR_MUTE: + // MUTE falls through to decline + case IOR_DECLINE: + // DECLINE. The math for the dialog works, because the decline + // for inventory_offered, task_inventory_offer or + // group_notice_inventory is 2 greater than the offer integer value. + // Generates IM_INVENTORY_DECLINED, IM_TASK_INVENTORY_DECLINED, + // or IM_GROUP_NOTICE_INVENTORY_DECLINED + default: + // close button probably (or any of the fall-throughs from above) + msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 2)); + msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE); + // send the message + msg->sendReliable(mHost); + + log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +"."; + chat.mText = log_message; + if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) ) // muting for SL-42269 + { + chat.mMuted = TRUE; + } + LLFloaterChat::addChatHistory(chat); + + // If it's from an agent, we have to fetch the item to throw + // it away. If it's from a task or group, just denying the + // request will suffice to discard the item. + if(IM_INVENTORY_OFFERED == mIM) + { + LLInventoryFetchComboObserver::folder_ref_t folders; + LLInventoryFetchComboObserver::item_ref_t items; + items.push_back(mObjectID); + LLDiscardAgentOffer* discard_agent_offer; + discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID); + discard_agent_offer->fetch(folders, items); + if(catp || (itemp && itemp->isComplete())) + { + discard_agent_offer->done(); + } + else + { + opener = discard_agent_offer; + } + + } + if (busy && (!mFromGroup && !mFromObject)) + { + busy_message(msg,mFromID); + } + break; + } + + if(IM_INVENTORY_OFFERED == mIM) + { + // add buddy to recent people list + LLRecentPeople::instance().add(mFromID); + } + + if(opener) + { + gInventory.addObserver(opener); + } + + delete this; + return false; +} + + +void inventory_offer_handler(LLOfferInfo* info, BOOL from_task) +{ + //Until throttling is implmented, busy mode should reject inventory instead of silently + //accepting it. SEE SL-39554 + if (gAgent.getBusy()) + { + info->forceResponse(IOR_BUSY); + return; + } + + //If muted, don't even go through the messaging stuff. Just curtail the offer here. + if (LLMuteList::getInstance()->isMuted(info->mFromID, info->mFromName)) + { + info->forceResponse(IOR_MUTE); + return; + } + + // Avoid the Accept/Discard dialog if the user so desires. JC + if (gSavedSettings.getBOOL("AutoAcceptNewInventory") + && (info->mType == LLAssetType::AT_NOTECARD + || info->mType == LLAssetType::AT_LANDMARK + || info->mType == LLAssetType::AT_TEXTURE)) + { + // For certain types, just accept the items into the inventory, + // and possibly open them on receipt depending upon "ShowNewInventory". + info->forceResponse(IOR_ACCEPT); + return; + } + + // Strip any SLURL from the message display. (DEV-2754) + std::string msg = info->mDesc; + int indx = msg.find(" ( http://slurl.com/secondlife/"); + if(indx >= 0) + { + LLStringUtil::truncate(msg, indx); + } + + LLSD args; + args["[OBJECTNAME]"] = msg; + + LLSD payload; + + // must protect against a NULL return from lookupHumanReadable() + std::string typestr = ll_safe_string(LLAssetType::lookupHumanReadable(info->mType)); + if (!typestr.empty()) + { + args["OBJECTTYPE"] = typestr; + } + else + { + LL_WARNS("Messaging") << "LLAssetType::lookupHumanReadable() returned NULL - probably bad asset type: " << info->mType << LL_ENDL; + args["OBJECTTYPE"] = ""; + + // This seems safest, rather than propagating bogosity + LL_WARNS("Messaging") << "Forcing an inventory-decline for probably-bad asset type." << LL_ENDL; + info->forceResponse(IOR_DECLINE); + return; + } + + // Name cache callbacks don't store userdata, so can't save + // off the LLOfferInfo. Argh. + BOOL name_found = FALSE; + if (info->mFromGroup) + { + std::string group_name; + if (gCacheName->getGroupName(info->mFromID, group_name)) + { + args["FIRST"] = group_name; + args["LAST"] = ""; + name_found = TRUE; + } + } + else + { + std::string first_name, last_name; + if (gCacheName->getName(info->mFromID, first_name, last_name)) + { + args["FIRST"] = first_name; + args["LAST"] = last_name; + name_found = TRUE; + } + } + + payload["from_id"] = info->mFromID; + args["OBJECTFROMNAME"] = info->mFromName; + args["NAME"] = info->mFromName; + + LLNotification::Params p("ObjectGiveItem"); + p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2)); + + if (from_task) + { + p.name = name_found ? "ObjectGiveItem" : "ObjectGiveItemUnknownUser"; + } + else + { + p.name = "UserGiveItem"; + } + + LLNotifications::instance().add(p); +} + +bool lure_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = 0; + if (response.isInteger()) + { + option = response.asInteger(); + } + else + { + option = LLNotification::getSelectedOption(notification, response); + } + + LLUUID from_id = notification["payload"]["from_id"].asUUID(); + LLUUID lure_id = notification["payload"]["lure_id"].asUUID(); + BOOL godlike = notification["payload"]["godlike"].asBoolean(); + + switch(option) + { + case 0: + { + // accept + gAgent.teleportViaLure(lure_id, godlike); + } + break; + case 1: + default: + // decline + send_simple_im(from_id, + LLStringUtil::null, + IM_LURE_DECLINED, + lure_id); + break; + } + return false; +} +static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback); + +bool goto_url_callback(const LLSD& notification, const LLSD& response) +{ + std::string url = notification["payload"]["url"].asString(); + S32 option = LLNotification::getSelectedOption(notification, response); + if(1 == option) + { + LLWeb::loadURL(url); + } + return false; +} +static LLNotificationFunctorRegistration goto_url_callback_reg("GotoURL", goto_url_callback); + +void process_improved_im(LLMessageSystem *msg, void **user_data) +{ + if (gNoRender) + { + return; + } + LLUUID from_id; + BOOL from_group; + LLUUID to_id; + U8 offline; + U8 d = 0; + LLUUID session_id; + U32 timestamp; + std::string name; + std::string message; + U32 parent_estate_id = 0; + LLUUID region_id; + LLVector3 position; + U8 binary_bucket[MTUBYTES]; + S32 binary_bucket_size; + LLChat chat; + std::string buffer; + + // *TODO: Translate - need to fix the full name to first/last (maybe) + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, from_id); + msg->getBOOLFast(_PREHASH_MessageBlock, _PREHASH_FromGroup, from_group); + msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ToAgentID, to_id); + msg->getU8Fast( _PREHASH_MessageBlock, _PREHASH_Offline, offline); + msg->getU8Fast( _PREHASH_MessageBlock, _PREHASH_Dialog, d); + msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ID, session_id); + msg->getU32Fast( _PREHASH_MessageBlock, _PREHASH_Timestamp, timestamp); + //msg->getData("MessageBlock", "Count", &count); + msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_FromAgentName, name); + msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_Message, message); + msg->getU32Fast(_PREHASH_MessageBlock, _PREHASH_ParentEstateID, parent_estate_id); + msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_RegionID, region_id); + msg->getVector3Fast(_PREHASH_MessageBlock, _PREHASH_Position, position); + msg->getBinaryDataFast( _PREHASH_MessageBlock, _PREHASH_BinaryBucket, binary_bucket, 0, 0, MTUBYTES); + binary_bucket_size = msg->getSizeFast(_PREHASH_MessageBlock, _PREHASH_BinaryBucket); + EInstantMessage dialog = (EInstantMessage)d; + + // make sure that we don't have an empty or all-whitespace name + LLStringUtil::trim(name); + if (name.empty()) + { + name = LLTrans::getString("Unnamed"); + } + + BOOL is_busy = gAgent.getBusy(); + BOOL is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat); + BOOL is_linden = LLMuteList::getInstance()->isLinden(name); + BOOL is_owned_by_me = FALSE; + BOOL is_friend = (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL) ? false : true; + BOOL accept_im_from_only_friend = gSavedSettings.getBOOL("VoiceCallsFriendsOnly"); + + chat.mMuted = is_muted && !is_linden; + chat.mFromID = from_id; + chat.mFromName = name; + chat.mSourceType = (from_id.isNull() || (name == std::string(SYSTEM_FROM))) ? CHAT_SOURCE_SYSTEM : CHAT_SOURCE_AGENT; + + LLViewerObject *source = gObjectList.findObject(session_id); //Session ID is probably the wrong thing. + if (source) + { + is_owned_by_me = source->permYouOwner(); + } + + std::string separator_string(": "); + int message_offset = 0; + + //Handle IRC styled /me messages. + std::string prefix = message.substr(0, 4); + if (prefix == "/me " || prefix == "/me'") + { + separator_string = ""; + message_offset = 3; + } + + LLSD args; + switch(dialog) + { + case IM_CONSOLE_AND_CHAT_HISTORY: + // These are used for system messages, hence don't need the name, + // as it is always "Second Life". + // *TODO: Translate + args["MESSAGE"] = message; + + // Note: don't put the message in the IM history, even though was sent + // via the IM mechanism. + LLNotifications::instance().add("SystemMessageTip",args); + break; + + case IM_NOTHING_SPECIAL: + // Don't show dialog, just do IM + if (!gAgent.isGodlike() + && gAgent.getRegion()->isPrelude() + && to_id.isNull() ) + { + // do nothing -- don't distract newbies in + // Prelude with global IMs + } + else if (offline == IM_ONLINE && !is_linden && is_busy && name != SYSTEM_FROM) + { + // return a standard "busy" message, but only do it to online IM + // (i.e. not other auto responses and not store-and-forward IM) + if (!gIMMgr->hasSession(session_id)) + { + // if there is not a panel for this conversation (i.e. it is a new IM conversation + // initiated by the other party) then... + std::string my_name; + LLAgentUI::buildFullname(my_name); + std::string response = gSavedPerAccountSettings.getString("BusyModeResponse2"); + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + from_id, + my_name, + response, + IM_ONLINE, + IM_BUSY_AUTO_RESPONSE, + session_id); + gAgent.sendReliableMessage(); + } + + // now store incoming IM in chat history + + buffer = message.substr(message_offset); + + LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; + + // add to IM panel, but do not bother the user + gIMMgr->addMessage( + session_id, + from_id, + name, + buffer, + LLStringUtil::null, + dialog, + parent_estate_id, + region_id, + position, + true); + + // pretend this is chat generated by self, so it does not show up on screen + chat.mText = std::string("IM: ") + name + separator_string + message.substr(message_offset); + LLFloaterChat::addChat( chat, TRUE, TRUE ); + } + else if (from_id.isNull()) + { + // Messages from "Second Life" ID don't go to IM history + // messages which should be routed to IM window come from a user ID with name=SYSTEM_NAME + chat.mText = name + ": " + message; + LLFloaterChat::addChat(chat, FALSE, FALSE); + } + else if (to_id.isNull()) + { + // Message to everyone from GOD + args["NAME"] = name; + args["MESSAGE"] = message; + LLNotifications::instance().add("GodMessage", args); + + // Treat like a system message and put in chat history. + // Claim to be from a local agent so it doesn't go into + // console. + chat.mText = name + separator_string + message.substr(message_offset); + + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD()); + if(nearby_chat) + { + nearby_chat->addMessage(chat); + } + } + else + { + // standard message, not from system + std::string saved; + if(offline == IM_OFFLINE) + { + saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str()); + } + buffer = saved + message.substr(message_offset); + + LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; + + bool mute_im = is_muted; + if(accept_im_from_only_friend&&!is_friend) + { + mute_im = true; + } + if (!mute_im || is_linden) + { + gIMMgr->addMessage( + session_id, + from_id, + name, + buffer, + LLStringUtil::null, + dialog, + parent_estate_id, + region_id, + position, + true); + chat.mText = std::string("IM: ") + name + separator_string + saved + message.substr(message_offset); + + BOOL local_agent = FALSE; + LLFloaterChat::addChat( chat, TRUE, local_agent ); + } + else + { + // muted user, so don't start an IM session, just record line in chat + // history. Pretend the chat is from a local agent, + // so it will go into the history but not be shown on screen. + chat.mText = buffer; + BOOL local_agent = TRUE; + LLFloaterChat::addChat( chat, TRUE, local_agent ); + } + } + break; + + case IM_TYPING_START: + { + LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem); + gIMMgr->processIMTypingStart(im_info); + } + break; + + case IM_TYPING_STOP: + { + LLPointer<LLIMInfo> im_info = new LLIMInfo(gMessageSystem); + gIMMgr->processIMTypingStop(im_info); + } + break; + + case IM_MESSAGEBOX: + { + // This is a block, modeless dialog. + //*TODO: Translate + args["MESSAGE"] = message; + LLNotifications::instance().add("SystemMessage", args); + } + break; + case IM_GROUP_NOTICE: + case IM_GROUP_NOTICE_REQUESTED: + { + LL_INFOS("Messaging") << "Received IM_GROUP_NOTICE message." << LL_ENDL; + // Read the binary bucket for more information. + struct notice_bucket_header_t + { + U8 has_inventory; + U8 asset_type; + LLUUID group_id; + }; + struct notice_bucket_full_t + { + struct notice_bucket_header_t header; + U8 item_name[DB_INV_ITEM_NAME_BUF_SIZE]; + }* notice_bin_bucket; + + // Make sure the binary bucket is big enough to hold the header + // and a null terminated item name. + if ( (binary_bucket_size < (S32)((sizeof(notice_bucket_header_t) + sizeof(U8)))) + || (binary_bucket[binary_bucket_size - 1] != '\0') ) + { + LL_WARNS("Messaging") << "Malformed group notice binary bucket" << LL_ENDL; + break; + } + + notice_bin_bucket = (struct notice_bucket_full_t*) &binary_bucket[0]; + U8 has_inventory = notice_bin_bucket->header.has_inventory; + U8 asset_type = notice_bin_bucket->header.asset_type; + LLUUID group_id = notice_bin_bucket->header.group_id; + std::string item_name = ll_safe_string((const char*) notice_bin_bucket->item_name); + + // If there is inventory, give the user the inventory offer. + LLOfferInfo* info = NULL; + + if (has_inventory) + { + info = new LLOfferInfo; + + info->mIM = IM_GROUP_NOTICE; + info->mFromID = from_id; + info->mFromGroup = from_group; + info->mTransactionID = session_id; + info->mType = (LLAssetType::EType) asset_type; + info->mFolderID = gInventory.findCategoryUUIDForType(info->mType); + std::string from_name; + + from_name += "A group member named "; + from_name += name; + + info->mFromName = from_name; + info->mDesc = item_name; + info->mHost = msg->getSender(); + } + + std::string str(message); + + // Tokenize the string. + // TODO: Support escaped tokens ("||" -> "|") + typedef boost::tokenizer<boost::char_separator<char> > tokenizer; + boost::char_separator<char> sep("|","",boost::keep_empty_tokens); + tokenizer tokens(str, sep); + tokenizer::iterator iter = tokens.begin(); + + std::string subj(*iter++); + std::string mes(*iter++); + + // Send the notification down the new path. + // For requested notices, we don't want to send the popups. + if (dialog != IM_GROUP_NOTICE_REQUESTED) + { + LLSD payload; + payload["subject"] = subj; + payload["message"] = mes; + payload["sender_name"] = name; + payload["group_id"] = group_id; + payload["inventory_name"] = item_name; + payload["inventory_offer"] = info ? info->asLLSD() : LLSD(); + + LLSD args; + args["SUBJECT"] = subj; + args["MESSAGE"] = mes; + LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).time_stamp(timestamp)); + } + + // Also send down the old path for now. + if (IM_GROUP_NOTICE_REQUESTED == dialog) + { + + LLPanelGroup::showNotice(subj,mes,group_id,has_inventory,item_name,info); + } + } + break; + case IM_GROUP_INVITATION: + { + //if (!is_linden && (is_busy || is_muted)) + if ((is_busy || is_muted)) + { + LLMessageSystem *msg = gMessageSystem; + busy_message(msg,from_id); + } + else + { + LL_INFOS("Messaging") << "Received IM_GROUP_INVITATION message." << LL_ENDL; + // Read the binary bucket for more information. + struct invite_bucket_t + { + S32 membership_fee; + LLUUID role_id; + }* invite_bucket; + + // Make sure the binary bucket is the correct size. + if (binary_bucket_size != sizeof(invite_bucket_t)) + { + LL_WARNS("Messaging") << "Malformed group invite binary bucket" << LL_ENDL; + break; + } + + invite_bucket = (struct invite_bucket_t*) &binary_bucket[0]; + S32 membership_fee = ntohl(invite_bucket->membership_fee); + + LLSD payload; + payload["transaction_id"] = session_id; + payload["group_id"] = from_id; + payload["name"] = name; + payload["message"] = message; + payload["fee"] = membership_fee; + + LLSD args; + args["MESSAGE"] = message; + LLNotifications::instance().add("JoinGroup", args, payload, join_group_response); + } + } + break; + + case IM_INVENTORY_OFFERED: + case IM_TASK_INVENTORY_OFFERED: + // Someone has offered us some inventory. + { + LLOfferInfo* info = new LLOfferInfo; + bool mute_im = false; + if (IM_INVENTORY_OFFERED == dialog) + { + struct offer_agent_bucket_t + { + S8 asset_type; + LLUUID object_id; + }* bucketp; + + if (sizeof(offer_agent_bucket_t) != binary_bucket_size) + { + LL_WARNS("Messaging") << "Malformed inventory offer from agent" << LL_ENDL; + break; + } + bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0]; + info->mType = (LLAssetType::EType) bucketp->asset_type; + info->mObjectID = bucketp->object_id; + + if(accept_im_from_only_friend&&!is_friend) + { + mute_im = true; + } + } + else + { + if (sizeof(S8) != binary_bucket_size) + { + LL_WARNS("Messaging") << "Malformed inventory offer from object" << LL_ENDL; + break; + } + info->mType = (LLAssetType::EType) binary_bucket[0]; + info->mObjectID = LLUUID::null; + } + + info->mIM = dialog; + info->mFromID = from_id; + info->mFromGroup = from_group; + info->mTransactionID = session_id; + info->mFolderID = gInventory.findCategoryUUIDForType(info->mType); + + if (dialog == IM_TASK_INVENTORY_OFFERED) + { + info->mFromObject = TRUE; + } + else + { + info->mFromObject = FALSE; + } + info->mFromName = name; + info->mDesc = message; + info->mHost = msg->getSender(); + //if (((is_busy && !is_owned_by_me) || is_muted)) + if ( is_muted || mute_im) + { + // Same as closing window + info->forceResponse(IOR_DECLINE); + } + else + { + inventory_offer_handler(info, dialog == IM_TASK_INVENTORY_OFFERED); + } + } + break; + + case IM_INVENTORY_ACCEPTED: + { + args["NAME"] = name; + LLNotifications::instance().add("InventoryAccepted", args); + break; + } + case IM_INVENTORY_DECLINED: + { + args["NAME"] = name; + LLNotifications::instance().add("InventoryDeclined", args); + break; + } + // TODO: _DEPRECATED suffix as part of vote removal - DEV-24856 + case IM_GROUP_VOTE: + { + LL_WARNS("Messaging") << "Received IM: IM_GROUP_VOTE_DEPRECATED" << LL_ENDL; + } + break; + + case IM_GROUP_ELECTION_DEPRECATED: + { + LL_WARNS("Messaging") << "Received IM: IM_GROUP_ELECTION_DEPRECATED" << LL_ENDL; + } + break; + + case IM_SESSION_SEND: + { + if (!is_linden && is_busy) + { + return; + } + + // Only show messages if we have a session open (which + // should happen after you get an "invitation" + if ( !gIMMgr->hasSession(session_id) ) + { + return; + } + + // standard message, not from system + std::string saved; + if(offline == IM_OFFLINE) + { + saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str()); + } + buffer = saved + message.substr(message_offset); + BOOL is_this_agent = FALSE; + if(from_id == gAgentID) + { + is_this_agent = TRUE; + } + gIMMgr->addMessage( + session_id, + from_id, + name, + buffer, + ll_safe_string((char*)binary_bucket), + IM_SESSION_INVITE, + parent_estate_id, + region_id, + position, + true); + + chat.mText = std::string("IM: ") + name + separator_string + saved + message.substr(message_offset); + LLFloaterChat::addChat(chat, TRUE, is_this_agent); + } + break; + + case IM_FROM_TASK: + { + if (is_busy && !is_owned_by_me) + { + return; + } + + LLSD substitutions; + substitutions["MSG"] = message.substr(message_offset); + LLNotifications::instance().add("ServerObjectMessage", substitutions); + } + break; + case IM_FROM_TASK_AS_ALERT: + if (is_busy && !is_owned_by_me) + { + return; + } + { + // Construct a viewer alert for this message. + args["NAME"] = name; + args["MESSAGE"] = message; + LLNotifications::instance().add("ObjectMessage", args); + } + break; + case IM_BUSY_AUTO_RESPONSE: + if (is_muted) + { + LL_DEBUGS("Messaging") << "Ignoring busy response from " << from_id << LL_ENDL; + return; + } + else + { + // TODO: after LLTrans hits release, get "busy response" into translatable file + buffer = llformat("%s (%s): %s", name.c_str(), "busy response", message.substr(message_offset).c_str()); + gIMMgr->addMessage(session_id, from_id, name, buffer); + } + break; + + case IM_LURE_USER: + { + if (is_muted) + { + return; + } + else if (is_busy) + { + busy_message(msg,from_id); + } + else + { + LLSD args; + // *TODO: Translate -> [FIRST] [LAST] (maybe) + args["NAME"] = name; + args["MESSAGE"] = message; + LLSD payload; + payload["from_id"] = from_id; + payload["lure_id"] = session_id; + payload["godlike"] = FALSE; + LLNotifications::instance().add("TeleportOffered", args, payload); + } + } + break; + + case IM_GODLIKE_LURE_USER: + { + LLSD payload; + payload["from_id"] = from_id; + payload["lure_id"] = session_id; + payload["godlike"] = TRUE; + // do not show a message box, because you're about to be + // teleported. + LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0); + } + break; + + case IM_GOTO_URL: + { + LLSD args; + // n.b. this is for URLs sent by the system, not for + // URLs sent by scripts (i.e. llLoadURL) + if (binary_bucket_size <= 0) + { + LL_WARNS("Messaging") << "bad binary_bucket_size: " + << binary_bucket_size + << " - aborting function." << LL_ENDL; + return; + } + + std::string url; + + url.assign((char*)binary_bucket, binary_bucket_size-1); + args["MESSAGE"] = message; + args["URL"] = url; + LLSD payload; + payload["url"] = url; + LLNotifications::instance().add("GotoURL", args, payload ); + } + break; + + case IM_FRIENDSHIP_OFFERED: + { + LLSD payload; + payload["from_id"] = from_id; + payload["session_id"] = session_id;; + payload["online"] = (offline == IM_ONLINE); + payload["sender"] = msg->getSender().getIPandPort(); + + if (is_busy) + { + busy_message(msg, from_id); + LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1); + } + else if (is_muted) + { + LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1); + } + else + { + args["[NAME]"] = name; + if(message.empty()) + { + //support for frienship offers from clients before July 2008 + LLNotifications::instance().add("OfferFriendshipNoMessage", args, payload); + } + else + { + args["[MESSAGE]"] = message; + LLNotifications::instance().add("OfferFriendship", args, payload); + } + } + } + break; + + case IM_FRIENDSHIP_ACCEPTED: + { + // In the case of an offline IM, the formFriendship() may be extraneous + // as the database should already include the relationship. But it + // doesn't hurt for dupes. + LLAvatarTracker::formFriendship(from_id); + + std::vector<std::string> strings; + strings.push_back(from_id.asString()); + send_generic_message("requestonlinenotification", strings); + + args["NAME"] = name; + LLNotifications::instance().add("FriendshipAccepted", args); + } + break; + + case IM_FRIENDSHIP_DECLINED_DEPRECATED: + default: + LL_WARNS("Messaging") << "Instant message calling for unknown dialog " + << (S32)dialog << LL_ENDL; + break; + } + + LLWindow* viewer_window = gViewerWindow->getWindow(); + if (viewer_window && viewer_window->getMinimized()) + { + viewer_window->flashIcon(5.f); + } +} + +void busy_message (LLMessageSystem* msg, LLUUID from_id) +{ + if (gAgent.getBusy()) + { + std::string my_name; + LLAgentUI::buildFullname(my_name); + std::string response = gSavedPerAccountSettings.getString("BusyModeResponse2"); + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + from_id, + my_name, + response, + IM_ONLINE, + IM_BUSY_AUTO_RESPONSE); + gAgent.sendReliableMessage(); + } +} + +bool callingcard_offer_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + LLUUID fid; + LLUUID from_id; + LLMessageSystem* msg = gMessageSystem; + switch(option) + { + case 0: + // accept + msg->newMessageFast(_PREHASH_AcceptCallingCard); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_TransactionBlock); + msg->addUUIDFast(_PREHASH_TransactionID, notification["payload"]["transaction_id"].asUUID()); + fid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + msg->nextBlockFast(_PREHASH_FolderData); + msg->addUUIDFast(_PREHASH_FolderID, fid); + msg->sendReliable(LLHost(notification["payload"]["sender"].asString())); + break; + case 1: + // decline + msg->newMessageFast(_PREHASH_DeclineCallingCard); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_TransactionBlock); + msg->addUUIDFast(_PREHASH_TransactionID, notification["payload"]["transaction_id"].asUUID()); + msg->sendReliable(LLHost(notification["payload"]["sender"].asString())); + busy_message(msg, notification["payload"]["source_id"].asUUID()); + break; + default: + // close button probably, possibly timed out + break; + } + + return false; +} +static LLNotificationFunctorRegistration callingcard_offer_cb_reg("OfferCallingCard", callingcard_offer_callback); + +void process_offer_callingcard(LLMessageSystem* msg, void**) +{ + // someone has offered to form a friendship + LL_DEBUGS("Messaging") << "callingcard offer" << LL_ENDL; + + LLUUID source_id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, source_id); + LLUUID tid; + msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_TransactionID, tid); + + LLSD payload; + payload["transaction_id"] = tid; + payload["source_id"] = source_id; + payload["sender"] = msg->getSender().getIPandPort(); + + LLViewerObject* source = gObjectList.findObject(source_id); + LLSD args; + std::string source_name; + if(source && source->isAvatar()) + { + LLNameValue* nvfirst = source->getNVPair("FirstName"); + LLNameValue* nvlast = source->getNVPair("LastName"); + if (nvfirst && nvlast) + { + args["FIRST"] = nvfirst->getString(); + args["LAST"] = nvlast->getString(); + source_name = std::string(nvfirst->getString()) + " " + nvlast->getString(); + } + } + + if(!source_name.empty()) + { + if (gAgent.getBusy() + || LLMuteList::getInstance()->isMuted(source_id, source_name, LLMute::flagTextChat)) + { + // automatically decline offer + LLNotifications::instance().forceResponse(LLNotification::Params("OfferCallingCard").payload(payload), 1); + } + else + { + LLNotifications::instance().add("OfferCallingCard", args, payload); + } + } + else + { + LL_WARNS("Messaging") << "Calling card offer from an unknown source." << LL_ENDL; + } +} + +void process_accept_callingcard(LLMessageSystem* msg, void**) +{ + LLNotifications::instance().add("CallingCardAccepted"); +} + +void process_decline_callingcard(LLMessageSystem* msg, void**) +{ + LLNotifications::instance().add("CallingCardDeclined"); +} + + +void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) +{ + LLChat chat; + std::string mesg; + std::string from_name; + U8 source_temp; + U8 type_temp; + U8 audible_temp; + LLColor4 color(1.0f, 1.0f, 1.0f, 1.0f); + LLUUID from_id; + LLUUID owner_id; + BOOL is_owned_by_me = FALSE; + LLViewerObject* chatter; + + msg->getString("ChatData", "FromName", from_name); + chat.mFromName = from_name; + + msg->getUUID("ChatData", "SourceID", from_id); + chat.mFromID = from_id; + + // Object owner for objects + msg->getUUID("ChatData", "OwnerID", owner_id); + + msg->getU8Fast(_PREHASH_ChatData, _PREHASH_SourceType, source_temp); + chat.mSourceType = (EChatSourceType)source_temp; + + msg->getU8("ChatData", "ChatType", type_temp); + chat.mChatType = (EChatType)type_temp; + + msg->getU8Fast(_PREHASH_ChatData, _PREHASH_Audible, audible_temp); + chat.mAudible = (EChatAudible)audible_temp; + + chat.mTime = LLFrameTimer::getElapsedSeconds(); + + BOOL is_busy = gAgent.getBusy(); + + BOOL is_muted = FALSE; + BOOL is_linden = FALSE; + is_muted = LLMuteList::getInstance()->isMuted( + from_id, + from_name, + LLMute::flagTextChat) + || LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagTextChat); + is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT && + LLMuteList::getInstance()->isLinden(from_name); + + BOOL is_audible = (CHAT_AUDIBLE_FULLY == chat.mAudible); + chatter = gObjectList.findObject(from_id); + if (chatter) + { + chat.mPosAgent = chatter->getPositionAgent(); + + // Make swirly things only for talking objects. (not script debug messages, though) + if (chat.mSourceType == CHAT_SOURCE_OBJECT + && chat.mChatType != CHAT_TYPE_DEBUG_MSG) + { + LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent()); + psc->setSourceObject(chatter); + psc->setColor(color); + //We set the particles to be owned by the object's owner, + //just in case they should be muted by the mute list + psc->setOwnerUUID(owner_id); + LLViewerPartSim::getInstance()->addPartSource(psc); + } + + // record last audible utterance + if (is_audible + && (is_linden || (!is_muted && !is_busy))) + { + if (chat.mChatType != CHAT_TYPE_START + && chat.mChatType != CHAT_TYPE_STOP) + { + gAgent.heardChat(chat.mFromID); + } + } + + is_owned_by_me = chatter->permYouOwner(); + } + + if (is_audible) + { + BOOL visible_in_chat_bubble = FALSE; + std::string verb; + + color.setVec(1.f,1.f,1.f,1.f); + msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg); + + BOOL ircstyle = FALSE; + + // Look for IRC-style emotes here so chatbubbles work + 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; + } + + // Look for the start of typing so we can put "..." in the bubbles. + if (CHAT_TYPE_START == chat.mChatType) + { + LLLocalSpeakerMgr::getInstance()->setSpeakerTyping(from_id, TRUE); + + // Might not have the avatar constructed yet, eg on login. + if (chatter && chatter->isAvatar()) + { + ((LLVOAvatar*)chatter)->startTyping(); + } + return; + } + else if (CHAT_TYPE_STOP == chat.mChatType) + { + LLLocalSpeakerMgr::getInstance()->setSpeakerTyping(from_id, FALSE); + + // Might not have the avatar constructed yet, eg on login. + if (chatter && chatter->isAvatar()) + { + ((LLVOAvatar*)chatter)->stopTyping(); + } + return; + } + + // We have a real utterance now, so can stop showing "..." and proceed. + if (chatter && chatter->isAvatar()) + { + LLLocalSpeakerMgr::getInstance()->setSpeakerTyping(from_id, FALSE); + ((LLVOAvatar*)chatter)->stopTyping(); + + if (!is_muted && !is_busy) + { + visible_in_chat_bubble = gSavedSettings.getBOOL("UseChatBubbles"); + ((LLVOAvatar*)chatter)->addChat(chat); + } + } + + // Look for IRC-style emotes + if (ircstyle) + { + // set CHAT_STYLE_IRC to avoid adding Avatar Name as author of message. See EXT-656 + chat.mChatStyle = CHAT_STYLE_IRC; + + // Do nothing, ircstyle is fixed above for chat bubbles + } + else + { + switch(chat.mChatType) + { + case CHAT_TYPE_WHISPER: + verb = "(" + LLTrans::getString("whisper") + ")"; + break; + case CHAT_TYPE_DEBUG_MSG: + case CHAT_TYPE_OWNER: + case CHAT_TYPE_NORMAL: + verb = ""; + break; + case CHAT_TYPE_SHOUT: + verb = "(" + LLTrans::getString("shout") + ")"; + break; + case CHAT_TYPE_START: + case CHAT_TYPE_STOP: + LL_WARNS("Messaging") << "Got chat type start/stop in main chat processing." << LL_ENDL; + break; + default: + LL_WARNS("Messaging") << "Unknown type " << chat.mChatType << " in chat!" << LL_ENDL; + verb = ""; + break; + } + + + chat.mText = ""; + chat.mText += verb; + chat.mText += mesg; + } + + if (chatter) + { + chat.mPosAgent = chatter->getPositionAgent(); + } + + // truth table: + // LINDEN BUSY MUTED OWNED_BY_YOU TASK DISPLAY STORE IN HISTORY + // F F F F * Yes Yes + // F F F T * Yes Yes + // F F T F * No No + // F F T T * No No + // F T F F * No Yes + // F T F T * Yes Yes + // F T T F * No No + // F T T T * No No + // T * * * F Yes Yes + + chat.mMuted = is_muted && !is_linden; + + if (!visible_in_chat_bubble + && (is_linden || !is_busy || is_owned_by_me)) + { + // show on screen and add to history + LLNotificationsUI::LLNotificationManager::instance().onChat( + chat, LLNotificationsUI::NT_NEARBYCHAT); + + // adding temporarily so that communications window chat bar + // works until the new chat window is ready + chat.mText = from_name + ": " + chat.mText; + LLFloaterChat::addChat(chat, FALSE, FALSE); + } + else + { + LLNotificationsUI::LLNotificationManager::instance().onChat( + chat, LLNotificationsUI::NT_NEARBYCHAT); + // adding temporarily + LLFloaterChat::addChatHistory(chat); + } + } +} + + +// Simulator we're on is informing the viewer that the agent +// is starting to teleport (perhaps to another sim, perhaps to the +// same sim). If we initiated the teleport process by sending some kind +// of TeleportRequest, then this info is redundant, but if the sim +// initiated the teleport (via a script call, being killed, etc.) +// then this info is news to us. +void process_teleport_start(LLMessageSystem *msg, void**) +{ + U32 teleport_flags = 0x0; + msg->getU32("Info", "TeleportFlags", teleport_flags); + + if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) + { + gViewerWindow->setProgressCancelButtonVisible(FALSE); + } + else + { + gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Cancel")); + } + + // Freeze the UI and show progress bar + // Note: could add data here to differentiate between normal teleport and death. + + if( gAgent.getTeleportState() == LLAgent::TELEPORT_NONE ) + { + gTeleportDisplay = TRUE; + gAgent.setTeleportState( LLAgent::TELEPORT_START ); + make_ui_sound("UISndTeleportOut"); + + // Don't call LLFirstUse::useTeleport here because this could be + // due to being killed, which would send you home, not to a Telehub + } +} + +void process_teleport_progress(LLMessageSystem* msg, void**) +{ + LLUUID agent_id; + msg->getUUID("AgentData", "AgentID", agent_id); + if((gAgent.getID() != agent_id) + || (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE)) + { + LL_WARNS("Messaging") << "Unexpected teleport progress message." << LL_ENDL; + return; + } + U32 teleport_flags = 0x0; + msg->getU32("Info", "TeleportFlags", teleport_flags); + if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) + { + gViewerWindow->setProgressCancelButtonVisible(FALSE); + } + else + { + gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Cancel")); + } + std::string buffer; + msg->getString("Info", "Message", buffer); + LL_DEBUGS("Messaging") << "teleport progress: " << buffer << LL_ENDL; + + //Sorta hacky...default to using simulator raw messages + //if we don't find the coresponding mapping in our progress mappings + std::string message = buffer; + + if (LLAgent::sTeleportProgressMessages.find(buffer) != + LLAgent::sTeleportProgressMessages.end() ) + { + message = LLAgent::sTeleportProgressMessages[buffer]; + } + + gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages[message]); +} + +class LLFetchInWelcomeArea : public LLInventoryFetchDescendentsObserver +{ +public: + LLFetchInWelcomeArea() {} + virtual void done() + { + LLIsType is_landmark(LLAssetType::AT_LANDMARK); + LLIsType is_card(LLAssetType::AT_CALLINGCARD); + + LLInventoryModel::cat_array_t card_cats; + LLInventoryModel::item_array_t card_items; + LLInventoryModel::cat_array_t land_cats; + LLInventoryModel::item_array_t land_items; + + folder_ref_t::iterator it = mCompleteFolders.begin(); + folder_ref_t::iterator end = mCompleteFolders.end(); + for(; it != end; ++it) + { + gInventory.collectDescendentsIf( + (*it), + land_cats, + land_items, + LLInventoryModel::EXCLUDE_TRASH, + is_landmark); + gInventory.collectDescendentsIf( + (*it), + card_cats, + card_items, + LLInventoryModel::EXCLUDE_TRASH, + is_card); + } + LLSD args; + if ( land_items.count() > 0 ) + { // Show notification that they can now teleport to landmarks. Use a random landmark from the inventory + S32 random_land = ll_rand( land_items.count() - 1 ); + args["NAME"] = land_items[random_land]->getName(); + LLNotifications::instance().add("TeleportToLandmark",args); + } + if ( card_items.count() > 0 ) + { // Show notification that they can now contact people. Use a random calling card from the inventory + S32 random_card = ll_rand( card_items.count() - 1 ); + args["NAME"] = card_items[random_card]->getName(); + LLNotifications::instance().add("TeleportToPerson",args); + } + + gInventory.removeObserver(this); + delete this; + } +}; + + + +class LLPostTeleportNotifiers : public LLEventTimer +{ +public: + LLPostTeleportNotifiers(); + virtual ~LLPostTeleportNotifiers(); + + //function to be called at the supplied frequency + virtual BOOL tick(); +}; + +LLPostTeleportNotifiers::LLPostTeleportNotifiers() : LLEventTimer( 2.0 ) +{ +}; + +LLPostTeleportNotifiers::~LLPostTeleportNotifiers() +{ +} + +BOOL LLPostTeleportNotifiers::tick() +{ + BOOL all_done = FALSE; + if ( gAgent.getTeleportState() == LLAgent::TELEPORT_NONE ) + { + // get callingcards and landmarks available to the user arriving. + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + LLUUID folder_id; + folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); + if(folder_id.notNull()) + folders.push_back(folder_id); + folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + if(folder_id.notNull()) + folders.push_back(folder_id); + if(!folders.empty()) + { + LLFetchInWelcomeArea* fetcher = new LLFetchInWelcomeArea; + fetcher->fetchDescendents(folders); + if(fetcher->isEverythingComplete()) + { + fetcher->done(); + } + else + { + gInventory.addObserver(fetcher); + } + } + all_done = TRUE; + } + + return all_done; +} + + + +// Teleport notification from the simulator +// We're going to pretend to be a new agent +void process_teleport_finish(LLMessageSystem* msg, void**) +{ + LL_DEBUGS("Messaging") << "Got teleport location message" << LL_ENDL; + LLUUID agent_id; + msg->getUUIDFast(_PREHASH_Info, _PREHASH_AgentID, agent_id); + if (agent_id != gAgent.getID()) + { + LL_WARNS("Messaging") << "Got teleport notification for wrong agent!" << LL_ENDL; + return; + } + + // Do teleport effect for where you're leaving + // VEFFECT: TeleportStart + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); + effectp->setPositionGlobal(gAgent.getPositionGlobal()); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + LLHUDManager::getInstance()->sendEffects(); + + U32 location_id; + U32 sim_ip; + U16 sim_port; + LLVector3 pos, look_at; + U64 region_handle; + msg->getU32Fast(_PREHASH_Info, _PREHASH_LocationID, location_id); + msg->getIPAddrFast(_PREHASH_Info, _PREHASH_SimIP, sim_ip); + msg->getIPPortFast(_PREHASH_Info, _PREHASH_SimPort, sim_port); + //msg->getVector3Fast(_PREHASH_Info, _PREHASH_Position, pos); + //msg->getVector3Fast(_PREHASH_Info, _PREHASH_LookAt, look_at); + msg->getU64Fast(_PREHASH_Info, _PREHASH_RegionHandle, region_handle); + U32 teleport_flags; + msg->getU32Fast(_PREHASH_Info, _PREHASH_TeleportFlags, teleport_flags); + + + std::string seedCap; + msg->getStringFast(_PREHASH_Info, _PREHASH_SeedCapability, seedCap); + + // update home location if we are teleporting out of prelude - specific to teleporting to welcome area + if((teleport_flags & TELEPORT_FLAGS_SET_HOME_TO_TARGET) + && (!gAgent.isGodlike())) + { + gAgent.setHomePosRegion(region_handle, pos); + + // Create a timer that will send notices when teleporting is all finished. Since this is + // based on the LLEventTimer class, it will be managed by that class and not orphaned or leaked. + new LLPostTeleportNotifiers(); + } + + LLHost sim_host(sim_ip, sim_port); + + // Viewer trusts the simulator. + gMessageSystem->enableCircuit(sim_host, TRUE); + LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host); + +/* + // send camera update to new region + gAgent.updateCamera(); + + // likewise make sure the camera is behind the avatar + gAgent.resetView(TRUE); + LLVector3 shift_vector = regionp->getPosRegionFromGlobal(gAgent.getRegion()->getOriginGlobal()); + gAgent.setRegion(regionp); + gObjectList.shiftObjects(shift_vector); + + if (gAgent.getAvatarObject()) + { + gAgent.getAvatarObject()->clearChatText(); + gAgent.slamLookAt(look_at); + } + gAgent.setPositionAgent(pos); + gAssetStorage->setUpstream(sim); + gCacheName->setUpstream(sim); +*/ + + // now, use the circuit info to tell simulator about us! + LL_INFOS("Messaging") << "process_teleport_finish() Enabling " + << sim_host << " with code " << msg->mOurCircuitCode << LL_ENDL; + msg->newMessageFast(_PREHASH_UseCircuitCode); + msg->nextBlockFast(_PREHASH_CircuitCode); + msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); + msg->sendReliable(sim_host); + + send_complete_agent_movement(sim_host); + gAgent.setTeleportState( LLAgent::TELEPORT_MOVING ); + gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["contacting"]); + + regionp->setSeedCapability(seedCap); + + // Don't send camera updates to the new region until we're + // actually there... + + + // Now do teleport effect for where you're going. + // VEFFECT: TeleportEnd + effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); + effectp->setPositionGlobal(gAgent.getPositionGlobal()); + + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + LLHUDManager::getInstance()->sendEffects(); + +// gTeleportDisplay = TRUE; +// gTeleportDisplayTimer.reset(); +// gViewerWindow->setShowProgress(TRUE); +} + +// stuff we have to do every time we get an AvatarInitComplete from a sim +/* +void process_avatar_init_complete(LLMessageSystem* msg, void**) +{ + LLVector3 agent_pos; + msg->getVector3Fast(_PREHASH_AvatarData, _PREHASH_Position, agent_pos); + agent_movement_complete(msg->getSender(), agent_pos); +} +*/ + +void process_agent_movement_complete(LLMessageSystem* msg, void**) +{ + gAgentMovementCompleted = true; + + LLUUID agent_id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); + LLUUID session_id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id); + if((gAgent.getID() != agent_id) || (gAgent.getSessionID() != session_id)) + { + LL_WARNS("Messaging") << "Incorrect id in process_agent_movement_complete()" + << LL_ENDL; + return; + } + + LL_DEBUGS("Messaging") << "process_agent_movement_complete()" << LL_ENDL; + + // *TODO: check timestamp to make sure the movement compleation + // makes sense. + LLVector3 agent_pos; + msg->getVector3Fast(_PREHASH_Data, _PREHASH_Position, agent_pos); + LLVector3 look_at; + msg->getVector3Fast(_PREHASH_Data, _PREHASH_LookAt, look_at); + U64 region_handle; + msg->getU64Fast(_PREHASH_Data, _PREHASH_RegionHandle, region_handle); + + std::string version_channel; + msg->getString("SimData", "ChannelVersion", version_channel); + + LLVOAvatar* avatarp = gAgent.getAvatarObject(); + if (!avatarp) + { + // Could happen if you were immediately god-teleported away on login, + // maybe other cases. Continue, but warn. + LL_WARNS("Messaging") << "agent_movement_complete() with NULL avatarp." << LL_ENDL; + } + + F32 x, y; + from_region_handle(region_handle, &x, &y); + LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); + if (!regionp) + { + if (gAgent.getRegion()) + { + LL_WARNS("Messaging") << "current region " << gAgent.getRegion()->getOriginGlobal() << LL_ENDL; + } + + LL_WARNS("Messaging") << "Agent being sent to invalid home region: " + << x << ":" << y + << " current pos " << gAgent.getPositionGlobal() + << LL_ENDL; + LLAppViewer::instance()->forceDisconnect("You were sent to an invalid region."); + return; + + } + + LL_INFOS("Messaging") << "Changing home region to " << x << ":" << y << LL_ENDL; + + // set our upstream host the new simulator and shuffle things as + // appropriate. + LLVector3 shift_vector = regionp->getPosRegionFromGlobal( + gAgent.getRegion()->getOriginGlobal()); + gAgent.setRegion(regionp); + gObjectList.shiftObjects(shift_vector); + gAssetStorage->setUpstream(msg->getSender()); + gCacheName->setUpstream(msg->getSender()); + gViewerThrottle.sendToSim(); + gViewerWindow->sendShapeToSim(); + + bool is_teleport = gAgent.getTeleportState() == LLAgent::TELEPORT_MOVING; + + if( is_teleport ) + { + // Force the camera back onto the agent, don't animate. + gAgent.setFocusOnAvatar(TRUE, FALSE); + gAgent.slamLookAt(look_at); + gAgent.updateCamera(); + + gAgent.setTeleportState( LLAgent::TELEPORT_START_ARRIVAL ); + + // set the appearance on teleport since the new sim does not + // know what you look like. + gAgent.sendAgentSetAppearance(); + + if (avatarp) + { + // Chat the "back" SLURL. (DEV-4907) + LLChat chat("Teleport completed from " + gAgent.getTeleportSourceSLURL()); + chat.mSourceType = CHAT_SOURCE_SYSTEM; + LLFloaterChat::addChatHistory(chat); + + // Set the new position + avatarp->setPositionAgent(agent_pos); + avatarp->clearChat(); + avatarp->slamPosition(); + } + } + else + { + // This is likely just the initial logging in phase. + gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); + } + + if ( LLTracker::isTracking(NULL) ) + { + // Check distance to beacon, if < 5m, remove beacon + LLVector3d beacon_pos = LLTracker::getTrackedPositionGlobal(); + LLVector3 beacon_dir(agent_pos.mV[VX] - (F32)fmod(beacon_pos.mdV[VX], 256.0), agent_pos.mV[VY] - (F32)fmod(beacon_pos.mdV[VY], 256.0), 0); + if (beacon_dir.magVecSquared() < 25.f) + { + LLTracker::stopTracking(NULL); + } + else if ( is_teleport ) + { + //look at the beacon + LLVector3 global_agent_pos = agent_pos; + global_agent_pos[0] += x; + global_agent_pos[1] += y; + look_at = (LLVector3)beacon_pos - global_agent_pos; + look_at.normVec(); + gAgent.slamLookAt(look_at); + } + } + + // TODO: Put back a check for flying status! DK 12/19/05 + // Sim tells us whether the new position is off the ground + /* + if (teleport_flags & TELEPORT_FLAGS_IS_FLYING) + { + gAgent.setFlying(TRUE); + } + else + { + gAgent.setFlying(FALSE); + } + */ + + send_agent_update(TRUE, TRUE); + + if (gAgent.getRegion()->getBlockFly()) + { + gAgent.setFlying(gAgent.canFly()); + } + + // force simulator to recognize busy state + if (gAgent.getBusy()) + { + gAgent.setBusy(); + } + else + { + gAgent.clearBusy(); + } + + if (avatarp) + { + avatarp->mFootPlane.clearVec(); + } + + // send walk-vs-run status + gAgent.sendWalkRun(gAgent.getRunning() || gAgent.getAlwaysRun()); + + // If the server version has changed, display an info box and offer + // to display the release notes, unless this is the initial log in. + if (gLastVersionChannel == version_channel) + { + return; + } + + if (!gLastVersionChannel.empty()) + { + LLSD payload; + payload["message"] = version_channel; + LLNotifications::instance().add("ServerVersionChanged", LLSD(), payload, server_version_changed_callback); + } + + gLastVersionChannel = version_channel; +} + +bool server_version_changed_callback(const LLSD& notification, const LLSD& response) +{ + if(notification["payload"]["message"].asString() =="") + return false; + std::string url ="http://wiki.secondlife.com/wiki/Release_Notes/"; + //parse the msg string + std::string server_version = notification["payload"]["message"].asString(); + std::vector<std::string> s_vect; + boost::algorithm::split(s_vect, server_version, isspace); + for(U32 i = 0; i < s_vect.size(); i++) + { + if (i != (s_vect.size() - 1)) + { + if(i != (s_vect.size() - 2)) + { + url += s_vect[i] + "_"; + } + else + { + url += s_vect[i] + "/"; + } + } + else + { + url += s_vect[i].substr(0,4); + } + } + + LLWeb::loadURL(url); + return false; +} + + +void process_crossed_region(LLMessageSystem* msg, void**) +{ + LLUUID agent_id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); + LLUUID session_id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id); + if((gAgent.getID() != agent_id) || (gAgent.getSessionID() != session_id)) + { + LL_WARNS("Messaging") << "Incorrect id in process_crossed_region()" + << LL_ENDL; + return; + } + LL_INFOS("Messaging") << "process_crossed_region()" << LL_ENDL; + + U32 sim_ip; + msg->getIPAddrFast(_PREHASH_RegionData, _PREHASH_SimIP, sim_ip); + U16 sim_port; + msg->getIPPortFast(_PREHASH_RegionData, _PREHASH_SimPort, sim_port); + LLHost sim_host(sim_ip, sim_port); + U64 region_handle; + msg->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); + + std::string seedCap; + msg->getStringFast(_PREHASH_RegionData, _PREHASH_SeedCapability, seedCap); + + send_complete_agent_movement(sim_host); + + LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host); + regionp->setSeedCapability(seedCap); +} + + + +// Sends avatar and camera information to simulator. +// Sent roughly once per frame, or 20 times per second, whichever is less often + +const F32 THRESHOLD_HEAD_ROT_QDOT = 0.9997f; // ~= 2.5 degrees -- if its less than this we need to update head_rot +const F32 MAX_HEAD_ROT_QDOT = 0.99999f; // ~= 0.5 degrees -- if its greater than this then no need to update head_rot + // between these values we delay the updates (but no more than one second) + + +void send_agent_update(BOOL force_send, BOOL send_reliable) +{ + if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) + { + // We don't care if they want to send an agent update, they're not allowed to until the simulator + // that's the target is ready to receive them (after avatar_init_complete is received) + return; + } + + // We have already requested to log out. Don't send agent updates. + if(LLAppViewer::instance()->logoutRequestSent()) + { + return; + } + + // no region to send update to + if(gAgent.getRegion() == NULL) + { + return; + } + + const F32 TRANSLATE_THRESHOLD = 0.01f; + + // NOTA BENE: This is (intentionally?) using the small angle sine approximation to test for rotation + // Plus, there is an extra 0.5 in the mix since the perpendicular between last_camera_at and getAtAxis() bisects cam_rot_change + // Thus, we're actually testing against 0.2 degrees + const F32 ROTATION_THRESHOLD = 0.1f * 2.f*F_PI/360.f; // Rotation thresh 0.2 deg, see note above + + const U8 DUP_MSGS = 1; // HACK! number of times to repeat data on motionless agent + + // Store data on last sent update so that if no changes, no send + static LLVector3 last_camera_pos_agent, + last_camera_at, + last_camera_left, + last_camera_up; + + static LLVector3 cam_center_chg, + cam_rot_chg; + + static LLQuaternion last_head_rot; + static U32 last_control_flags = 0; + static U8 last_render_state; + static U8 duplicate_count = 0; + static F32 head_rot_chg = 1.0; + static U8 last_flags; + + LLMessageSystem *msg = gMessageSystem; + LLVector3 camera_pos_agent; // local to avatar's region + U8 render_state; + + LLQuaternion body_rotation = gAgent.getFrameAgent().getQuaternion(); + LLQuaternion head_rotation = gAgent.getHeadRotation(); + + camera_pos_agent = gAgent.getCameraPositionAgent(); + + render_state = gAgent.getRenderState(); + + U32 control_flag_change = 0; + U8 flag_change = 0; + + cam_center_chg = last_camera_pos_agent - camera_pos_agent; + cam_rot_chg = last_camera_at - LLViewerCamera::getInstance()->getAtAxis(); + + // If a modifier key is held down, turn off + // LBUTTON and ML_LBUTTON so that using the camera (alt-key) doesn't + // trigger a control event. + U32 control_flags = gAgent.getControlFlags(); + MASK key_mask = gKeyboard->currentMask(TRUE); + if (key_mask & MASK_ALT || key_mask & MASK_CONTROL) + { + control_flags &= ~( AGENT_CONTROL_LBUTTON_DOWN | + AGENT_CONTROL_ML_LBUTTON_DOWN ); + control_flags |= AGENT_CONTROL_LBUTTON_UP | + AGENT_CONTROL_ML_LBUTTON_UP ; + } + + control_flag_change = last_control_flags ^ control_flags; + + U8 flags = AU_FLAGS_NONE; + if (gAgent.isGroupTitleHidden()) + { + flags |= AU_FLAGS_HIDETITLE; + } + if (gAgent.getAutoPilot()) + { + flags |= AU_FLAGS_CLIENT_AUTOPILOT; + } + + flag_change = last_flags ^ flags; + + head_rot_chg = dot(last_head_rot, head_rotation); + + if (force_send || + (cam_center_chg.magVec() > TRANSLATE_THRESHOLD) || + (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT) || + (last_render_state != render_state) || + (cam_rot_chg.magVec() > ROTATION_THRESHOLD) || + control_flag_change != 0 || + flag_change != 0) + { +/* + if (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT) + { + //LL_INFOS("Messaging") << "head rot " << head_rotation << LL_ENDL; + LL_INFOS("Messaging") << "head_rot_chg = " << head_rot_chg << LL_ENDL; + } + if (cam_rot_chg.magVec() > ROTATION_THRESHOLD) + { + LL_INFOS("Messaging") << "cam rot " << cam_rot_chg.magVec() << LL_ENDL; + } + if (cam_center_chg.magVec() > TRANSLATE_THRESHOLD) + { + LL_INFOS("Messaging") << "cam center " << cam_center_chg.magVec() << LL_ENDL; + } +// if (drag_delta_chg.magVec() > TRANSLATE_THRESHOLD) +// { +// LL_INFOS("Messaging") << "drag delta " << drag_delta_chg.magVec() << LL_ENDL; +// } + if (control_flag_change) + { + LL_INFOS("Messaging") << "dcf = " << control_flag_change << LL_ENDL; + } +*/ + + duplicate_count = 0; + } + else + { + duplicate_count++; + + if (head_rot_chg < MAX_HEAD_ROT_QDOT && duplicate_count < AGENT_UPDATES_PER_SECOND) + { + // The head_rotation is sent for updating things like attached guns. + // We only trigger a new update when head_rotation deviates beyond + // some threshold from the last update, however this can break fine + // adjustments when trying to aim an attached gun, so what we do here + // (where we would normally skip sending an update when nothing has changed) + // is gradually reduce the threshold to allow a better update to + // eventually get sent... should update to within 0.5 degrees in less + // than a second. + if (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT + (MAX_HEAD_ROT_QDOT - THRESHOLD_HEAD_ROT_QDOT) * duplicate_count / AGENT_UPDATES_PER_SECOND) + { + duplicate_count = 0; + } + else + { + return; + } + } + else + { + return; + } + } + + if (duplicate_count < DUP_MSGS && !gDisconnected) + { + // Build the message + msg->newMessageFast(_PREHASH_AgentUpdate); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addQuatFast(_PREHASH_BodyRotation, body_rotation); + msg->addQuatFast(_PREHASH_HeadRotation, head_rotation); + msg->addU8Fast(_PREHASH_State, render_state); + msg->addU8Fast(_PREHASH_Flags, flags); + +// if (camera_pos_agent.mV[VY] > 255.f) +// { +// LL_INFOS("Messaging") << "Sending camera center " << camera_pos_agent << LL_ENDL; +// } + + msg->addVector3Fast(_PREHASH_CameraCenter, camera_pos_agent); + msg->addVector3Fast(_PREHASH_CameraAtAxis, LLViewerCamera::getInstance()->getAtAxis()); + msg->addVector3Fast(_PREHASH_CameraLeftAxis, LLViewerCamera::getInstance()->getLeftAxis()); + msg->addVector3Fast(_PREHASH_CameraUpAxis, LLViewerCamera::getInstance()->getUpAxis()); + msg->addF32Fast(_PREHASH_Far, gAgent.mDrawDistance); + + msg->addU32Fast(_PREHASH_ControlFlags, control_flags); + + if (gDebugClicks) + { + if (control_flags & AGENT_CONTROL_LBUTTON_DOWN) + { + LL_INFOS("Messaging") << "AgentUpdate left button down" << LL_ENDL; + } + + if (control_flags & AGENT_CONTROL_LBUTTON_UP) + { + LL_INFOS("Messaging") << "AgentUpdate left button up" << LL_ENDL; + } + } + + gAgent.enableControlFlagReset(); + + if (!send_reliable) + { + gAgent.sendMessage(); + } + else + { + gAgent.sendReliableMessage(); + } + +// LL_DEBUGS("Messaging") << "agent " << avatar_pos_agent << " cam " << camera_pos_agent << LL_ENDL; + + // Copy the old data + last_head_rot = head_rotation; + last_render_state = render_state; + last_camera_pos_agent = camera_pos_agent; + last_camera_at = LLViewerCamera::getInstance()->getAtAxis(); + last_camera_left = LLViewerCamera::getInstance()->getLeftAxis(); + last_camera_up = LLViewerCamera::getInstance()->getUpAxis(); + last_control_flags = control_flags; + last_flags = flags; + } +} + + + +// *TODO: Remove this dependency, or figure out a better way to handle +// this hack. +extern U32 gObjectBits; + +void process_object_update(LLMessageSystem *mesgsys, void **user_data) +{ + LLMemType mt(LLMemType::MTYPE_OBJECT); + // Update the data counters + if (mesgsys->getReceiveCompressedSize()) + { + gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + } + else + { + gObjectBits += mesgsys->getReceiveSize() * 8; + } + + // Update the object... + gObjectList.processObjectUpdate(mesgsys, user_data, OUT_FULL); +} + +void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data) +{ + LLMemType mt(LLMemType::MTYPE_OBJECT); + // Update the data counters + if (mesgsys->getReceiveCompressedSize()) + { + gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + } + else + { + gObjectBits += mesgsys->getReceiveSize() * 8; + } + + // Update the object... + gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_FULL_COMPRESSED); +} + +void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) +{ + LLMemType mt(LLMemType::MTYPE_OBJECT); + // Update the data counters + if (mesgsys->getReceiveCompressedSize()) + { + gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + } + else + { + gObjectBits += mesgsys->getReceiveSize() * 8; + } + + // Update the object... + gObjectList.processCachedObjectUpdate(mesgsys, user_data, OUT_FULL_CACHED); +} + + +void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_data) +{ + LLMemType mt(LLMemType::MTYPE_OBJECT); + if (mesgsys->getReceiveCompressedSize()) + { + gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + } + else + { + gObjectBits += mesgsys->getReceiveSize() * 8; + } + + gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_TERSE_IMPROVED); +} + +static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Objects"); + + +void process_kill_object(LLMessageSystem *mesgsys, void **user_data) +{ + LLFastTimer t(FTM_PROCESS_OBJECTS); + + LLUUID id; + U32 local_id; + S32 i; + S32 num_objects; + + num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); + + for (i = 0; i < num_objects; i++) + { + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); + + LLViewerObjectList::getUUIDFromLocal(id, + local_id, + gMessageSystem->getSenderIP(), + gMessageSystem->getSenderPort()); + if (id == LLUUID::null) + { + LL_DEBUGS("Messaging") << "Unknown kill for local " << local_id << LL_ENDL; + gObjectList.mNumUnknownKills++; + continue; + } + else + { + LL_DEBUGS("Messaging") << "Kill message for local " << local_id << LL_ENDL; + } + + LLSelectMgr::getInstance()->removeObjectFromSelections(id); + + // ...don't kill the avatar + if (!(id == gAgentID)) + { + LLViewerObject *objectp = gObjectList.findObject(id); + if (objectp) + { + // Display green bubble on kill + if ( gShowObjectUpdates ) + { + LLViewerObject* newobject; + newobject = gObjectList.createObjectViewer(LL_PCODE_LEGACY_TEXT_BUBBLE, objectp->getRegion()); + + LLVOTextBubble* bubble = (LLVOTextBubble*) newobject; + + bubble->mColor.setVec(0.f, 1.f, 0.f, 1.f); + bubble->setScale( 2.0f * bubble->getScale() ); + bubble->setPositionGlobal(objectp->getPositionGlobal()); + gPipeline.addObject(bubble); + } + + // Do the kill + gObjectList.killObject(objectp); + } + else + { + LL_WARNS("Messaging") << "Object in UUID lookup, but not on object list in kill!" << LL_ENDL; + gObjectList.mNumUnknownKills++; + } + } + } +} + +void process_time_synch(LLMessageSystem *mesgsys, void **user_data) +{ + LLVector3 sun_direction; + LLVector3 sun_ang_velocity; + F32 phase; + U64 space_time_usec; + + U32 seconds_per_day; + U32 seconds_per_year; + + // "SimulatorViewerTimeMessage" + mesgsys->getU64Fast(_PREHASH_TimeInfo, _PREHASH_UsecSinceStart, space_time_usec); + mesgsys->getU32Fast(_PREHASH_TimeInfo, _PREHASH_SecPerDay, seconds_per_day); + mesgsys->getU32Fast(_PREHASH_TimeInfo, _PREHASH_SecPerYear, seconds_per_year); + + // This should eventually be moved to an "UpdateHeavenlyBodies" message + mesgsys->getF32Fast(_PREHASH_TimeInfo, _PREHASH_SunPhase, phase); + mesgsys->getVector3Fast(_PREHASH_TimeInfo, _PREHASH_SunDirection, sun_direction); + mesgsys->getVector3Fast(_PREHASH_TimeInfo, _PREHASH_SunAngVelocity, sun_ang_velocity); + + LLWorld::getInstance()->setSpaceTimeUSec(space_time_usec); + + //LL_DEBUGS("Messaging") << "time_synch() - " << sun_direction << ", " << sun_ang_velocity + // << ", " << phase << LL_ENDL; + + gSky.setSunPhase(phase); + gSky.setSunTargetDirection(sun_direction, sun_ang_velocity); + if (!gNoRender && !(gSavedSettings.getBOOL("SkyOverrideSimSunPosition") || gSky.getOverrideSun())) + { + gSky.setSunDirection(sun_direction, sun_ang_velocity); + } +} + +void process_sound_trigger(LLMessageSystem *msg, void **) +{ + if (!gAudiop) return; + + U64 region_handle = 0; + F32 gain = 0; + LLUUID sound_id; + LLUUID owner_id; + LLUUID object_id; + LLUUID parent_id; + LLVector3 pos_local; + + msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_SoundID, sound_id); + msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_OwnerID, owner_id); + msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_ObjectID, object_id); + msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_ParentID, parent_id); + msg->getU64Fast(_PREHASH_SoundData, _PREHASH_Handle, region_handle); + msg->getVector3Fast(_PREHASH_SoundData, _PREHASH_Position, pos_local); + msg->getF32Fast(_PREHASH_SoundData, _PREHASH_Gain, gain); + + // adjust sound location to true global coords + LLVector3d pos_global = from_region_handle(region_handle); + pos_global.mdV[VX] += pos_local.mV[VX]; + pos_global.mdV[VY] += pos_local.mV[VY]; + pos_global.mdV[VZ] += pos_local.mV[VZ]; + + // Don't play a trigger sound if you can't hear it due + // to parcel "local audio only" settings. + if (!LLViewerParcelMgr::getInstance()->canHearSound(pos_global)) return; + + // Don't play sounds triggered by someone you muted. + if (LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagObjectSounds)) return; + + // Don't play sounds from an object you muted + if (LLMuteList::getInstance()->isMuted(object_id)) return; + + // Don't play sounds from an object whose parent you muted + if (parent_id.notNull() + && LLMuteList::getInstance()->isMuted(parent_id)) + { + return; + } + + // Don't play sounds from a region with maturity above current agent maturity + if( !gAgent.canAccessMaturityInRegion( region_handle ) ) + { + return; + } + + gAudiop->triggerSound(sound_id, owner_id, gain, LLAudioEngine::AUDIO_TYPE_SFX, pos_global); +} + +void process_preload_sound(LLMessageSystem *msg, void **user_data) +{ + if (!gAudiop) + { + return; + } + + LLUUID sound_id; + LLUUID object_id; + LLUUID owner_id; + + msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_SoundID, sound_id); + msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_ObjectID, object_id); + msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_OwnerID, owner_id); + + LLViewerObject *objectp = gObjectList.findObject(object_id); + if (!objectp) return; + + if (LLMuteList::getInstance()->isMuted(object_id)) return; + if (LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagObjectSounds)) return; + + LLAudioSource *sourcep = objectp->getAudioSource(owner_id); + if (!sourcep) return; + + LLAudioData *datap = gAudiop->getAudioData(sound_id); + + // Note that I don't actually do any loading of the + // audio data into a buffer at this point, as it won't actually + // help us out. + + // Don't play sounds from a region with maturity above current agent maturity + LLVector3d pos_global = objectp->getPositionGlobal(); + if( !gAgent.canAccessMaturityAtGlobal( pos_global ) ) + { + return; + } + + // Add audioData starts a transfer internally. + sourcep->addAudioData(datap, FALSE); +} + +void process_attached_sound(LLMessageSystem *msg, void **user_data) +{ + F32 gain = 0; + LLUUID sound_id; + LLUUID object_id; + LLUUID owner_id; + U8 flags; + + msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_SoundID, sound_id); + msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_ObjectID, object_id); + msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_OwnerID, owner_id); + msg->getF32Fast(_PREHASH_DataBlock, _PREHASH_Gain, gain); + msg->getU8Fast(_PREHASH_DataBlock, _PREHASH_Flags, flags); + + LLViewerObject *objectp = gObjectList.findObject(object_id); + if (!objectp) + { + // we don't know about this object, just bail + return; + } + + if (LLMuteList::getInstance()->isMuted(object_id)) return; + + if (LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagObjectSounds)) return; + + + // Don't play sounds from a region with maturity above current agent maturity + LLVector3d pos = objectp->getPositionGlobal(); + if( !gAgent.canAccessMaturityAtGlobal(pos) ) + { + return; + } + + objectp->setAttachedSound(sound_id, owner_id, gain, flags); +} + + +void process_attached_sound_gain_change(LLMessageSystem *mesgsys, void **user_data) +{ + F32 gain = 0; + LLUUID object_guid; + LLViewerObject *objectp = NULL; + + mesgsys->getUUIDFast(_PREHASH_DataBlock, _PREHASH_ObjectID, object_guid); + + if (!((objectp = gObjectList.findObject(object_guid)))) + { + // we don't know about this object, just bail + return; + } + + mesgsys->getF32Fast(_PREHASH_DataBlock, _PREHASH_Gain, gain); + + objectp->adjustAudioGain(gain); +} + + +void process_health_message(LLMessageSystem *mesgsys, void **user_data) +{ + F32 health; + + mesgsys->getF32Fast(_PREHASH_HealthData, _PREHASH_Health, health); + + if (gStatusBar) + { + gStatusBar->setHealth((S32)health); + } +} + + +void process_sim_stats(LLMessageSystem *msg, void **user_data) +{ + S32 count = msg->getNumberOfBlocks("Stat"); + for (S32 i = 0; i < count; ++i) + { + U32 stat_id; + F32 stat_value; + msg->getU32("Stat", "StatID", stat_id, i); + msg->getF32("Stat", "StatValue", stat_value, i); + switch (stat_id) + { + case LL_SIM_STAT_TIME_DILATION: + LLViewerStats::getInstance()->mSimTimeDilation.addValue(stat_value); + break; + case LL_SIM_STAT_FPS: + LLViewerStats::getInstance()->mSimFPS.addValue(stat_value); + break; + case LL_SIM_STAT_PHYSFPS: + LLViewerStats::getInstance()->mSimPhysicsFPS.addValue(stat_value); + break; + case LL_SIM_STAT_AGENTUPS: + LLViewerStats::getInstance()->mSimAgentUPS.addValue(stat_value); + break; + case LL_SIM_STAT_FRAMEMS: + LLViewerStats::getInstance()->mSimFrameMsec.addValue(stat_value); + break; + case LL_SIM_STAT_NETMS: + LLViewerStats::getInstance()->mSimNetMsec.addValue(stat_value); + break; + case LL_SIM_STAT_SIMOTHERMS: + LLViewerStats::getInstance()->mSimSimOtherMsec.addValue(stat_value); + break; + case LL_SIM_STAT_SIMPHYSICSMS: + LLViewerStats::getInstance()->mSimSimPhysicsMsec.addValue(stat_value); + break; + case LL_SIM_STAT_AGENTMS: + LLViewerStats::getInstance()->mSimAgentMsec.addValue(stat_value); + break; + case LL_SIM_STAT_IMAGESMS: + LLViewerStats::getInstance()->mSimImagesMsec.addValue(stat_value); + break; + case LL_SIM_STAT_SCRIPTMS: + LLViewerStats::getInstance()->mSimScriptMsec.addValue(stat_value); + break; + case LL_SIM_STAT_NUMTASKS: + LLViewerStats::getInstance()->mSimObjects.addValue(stat_value); + break; + case LL_SIM_STAT_NUMTASKSACTIVE: + LLViewerStats::getInstance()->mSimActiveObjects.addValue(stat_value); + break; + case LL_SIM_STAT_NUMAGENTMAIN: + LLViewerStats::getInstance()->mSimMainAgents.addValue(stat_value); + break; + case LL_SIM_STAT_NUMAGENTCHILD: + LLViewerStats::getInstance()->mSimChildAgents.addValue(stat_value); + break; + case LL_SIM_STAT_NUMSCRIPTSACTIVE: + LLViewerStats::getInstance()->mSimActiveScripts.addValue(stat_value); + break; + case LL_SIM_STAT_SCRIPT_EPS: + LLViewerStats::getInstance()->mSimScriptEPS.addValue(stat_value); + break; + case LL_SIM_STAT_INPPS: + LLViewerStats::getInstance()->mSimInPPS.addValue(stat_value); + break; + case LL_SIM_STAT_OUTPPS: + LLViewerStats::getInstance()->mSimOutPPS.addValue(stat_value); + break; + case LL_SIM_STAT_PENDING_DOWNLOADS: + LLViewerStats::getInstance()->mSimPendingDownloads.addValue(stat_value); + break; + case LL_SIM_STAT_PENDING_UPLOADS: + LLViewerStats::getInstance()->mSimPendingUploads.addValue(stat_value); + break; + case LL_SIM_STAT_PENDING_LOCAL_UPLOADS: + LLViewerStats::getInstance()->mSimPendingLocalUploads.addValue(stat_value); + break; + case LL_SIM_STAT_TOTAL_UNACKED_BYTES: + LLViewerStats::getInstance()->mSimTotalUnackedBytes.addValue(stat_value / 1024.f); + break; + case LL_SIM_STAT_PHYSICS_PINNED_TASKS: + LLViewerStats::getInstance()->mPhysicsPinnedTasks.addValue(stat_value); + break; + case LL_SIM_STAT_PHYSICS_LOD_TASKS: + LLViewerStats::getInstance()->mPhysicsLODTasks.addValue(stat_value); + break; + case LL_SIM_STAT_SIMPHYSICSSTEPMS: + LLViewerStats::getInstance()->mSimSimPhysicsStepMsec.addValue(stat_value); + break; + case LL_SIM_STAT_SIMPHYSICSSHAPEMS: + LLViewerStats::getInstance()->mSimSimPhysicsShapeUpdateMsec.addValue(stat_value); + break; + case LL_SIM_STAT_SIMPHYSICSOTHERMS: + LLViewerStats::getInstance()->mSimSimPhysicsOtherMsec.addValue(stat_value); + break; + case LL_SIM_STAT_SIMPHYSICSMEMORY: + LLViewerStats::getInstance()->mPhysicsMemoryAllocated.addValue(stat_value); + break; + case LL_SIM_STAT_SIMSPARETIME: + LLViewerStats::getInstance()->mSimSpareMsec.addValue(stat_value); + break; + case LL_SIM_STAT_SIMSLEEPTIME: + LLViewerStats::getInstance()->mSimSleepMsec.addValue(stat_value); + break; + case LL_SIM_STAT_IOPUMPTIME: + LLViewerStats::getInstance()->mSimPumpIOMsec.addValue(stat_value); + break; + default: + // Used to be a commented out warning. + LL_DEBUGS("Messaging") << "Unknown stat id" << stat_id << LL_ENDL; + break; + } + } + + /* + msg->getF32Fast(_PREHASH_Statistics, _PREHASH_PhysicsTimeDilation, time_dilation); + LLViewerStats::getInstance()->mSimTDStat.addValue(time_dilation); + + // Process information + // { CpuUsage F32 } + // { SimMemTotal F32 } + // { SimMemRSS F32 } + // { ProcessUptime F32 } + F32 cpu_usage; + F32 sim_mem_total; + F32 sim_mem_rss; + F32 process_uptime; + msg->getF32Fast(_PREHASH_Statistics, _PREHASH_CpuUsage, cpu_usage); + msg->getF32Fast(_PREHASH_Statistics, _PREHASH_SimMemTotal, sim_mem_total); + msg->getF32Fast(_PREHASH_Statistics, _PREHASH_SimMemRSS, sim_mem_rss); + msg->getF32Fast(_PREHASH_Statistics, _PREHASH_ProcessUptime, process_uptime); + LLViewerStats::getInstance()->mSimCPUUsageStat.addValue(cpu_usage); + LLViewerStats::getInstance()->mSimMemTotalStat.addValue(sim_mem_total); + LLViewerStats::getInstance()->mSimMemRSSStat.addValue(sim_mem_rss); + */ + + // + // Various hacks that aren't statistics, but are being handled here. + // + U32 max_tasks_per_region; + U32 region_flags; + msg->getU32("Region", "ObjectCapacity", max_tasks_per_region); + msg->getU32("Region", "RegionFlags", region_flags); + + LLViewerRegion* regionp = gAgent.getRegion(); + if (regionp) + { + BOOL was_flying = gAgent.getFlying(); + regionp->setRegionFlags(region_flags); + regionp->setMaxTasks(max_tasks_per_region); + // HACK: This makes agents drop from the sky if the region is + // set to no fly while people are still in the sim. + if (was_flying && regionp->getBlockFly()) + { + gAgent.setFlying(gAgent.canFly()); + } + } +} + + + +void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data) +{ + LLUUID animation_id; + LLUUID uuid; + S32 anim_sequence_id; + LLVOAvatar *avatarp; + + mesgsys->getUUIDFast(_PREHASH_Sender, _PREHASH_ID, uuid); + + //clear animation flags + avatarp = (LLVOAvatar *)gObjectList.findObject(uuid); + + if (!avatarp) + { + // no agent by this ID...error? + LL_WARNS("Messaging") << "Received animation state for unknown avatar" << uuid << LL_ENDL; + return; + } + + S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationList); + S32 num_source_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationSourceList); + + avatarp->mSignaledAnimations.clear(); + + if (avatarp->isSelf()) + { + LLUUID object_id; + + for( S32 i = 0; i < num_blocks; i++ ) + { + mesgsys->getUUIDFast(_PREHASH_AnimationList, _PREHASH_AnimID, animation_id, i); + mesgsys->getS32Fast(_PREHASH_AnimationList, _PREHASH_AnimSequenceID, anim_sequence_id, i); + + LL_DEBUGS("Messaging") << "Anim sequence ID: " << anim_sequence_id << LL_ENDL; + + avatarp->mSignaledAnimations[animation_id] = anim_sequence_id; + + if (i < num_source_blocks) + { + mesgsys->getUUIDFast(_PREHASH_AnimationSourceList, _PREHASH_ObjectID, object_id, i); + + LLViewerObject* object = gObjectList.findObject(object_id); + if (object) + { + object->mFlags |= FLAGS_ANIM_SOURCE; + + BOOL anim_found = FALSE; + LLVOAvatar::AnimSourceIterator anim_it = avatarp->mAnimationSources.find(object_id); + for (;anim_it != avatarp->mAnimationSources.end(); ++anim_it) + { + if (anim_it->second == animation_id) + { + anim_found = TRUE; + break; + } + } + + if (!anim_found) + { + avatarp->mAnimationSources.insert(LLVOAvatar::AnimationSourceMap::value_type(object_id, animation_id)); + } + } + } + } + } + else + { + for( S32 i = 0; i < num_blocks; i++ ) + { + mesgsys->getUUIDFast(_PREHASH_AnimationList, _PREHASH_AnimID, animation_id, i); + mesgsys->getS32Fast(_PREHASH_AnimationList, _PREHASH_AnimSequenceID, anim_sequence_id, i); + avatarp->mSignaledAnimations[animation_id] = anim_sequence_id; + } + } + + if (num_blocks) + { + avatarp->processAnimationStateChanges(); + } +} + +void process_avatar_appearance(LLMessageSystem *mesgsys, void **user_data) +{ + LLUUID uuid; + mesgsys->getUUIDFast(_PREHASH_Sender, _PREHASH_ID, uuid); + + LLVOAvatar* avatarp = (LLVOAvatar *)gObjectList.findObject(uuid); + if( avatarp ) + { + avatarp->processAvatarAppearance( mesgsys ); + } + else + { + LL_WARNS("Messaging") << "avatar_appearance sent for unknown avatar " << uuid << LL_ENDL; + } +} + +void process_camera_constraint(LLMessageSystem *mesgsys, void **user_data) +{ + LLVector4 cameraCollidePlane; + mesgsys->getVector4Fast(_PREHASH_CameraCollidePlane, _PREHASH_Plane, cameraCollidePlane); + + gAgent.setCameraCollidePlane(cameraCollidePlane); +} + +void near_sit_object(BOOL success, void *data) +{ + if (success) + { + // Send message to sit on object + gMessageSystem->newMessageFast(_PREHASH_AgentSit); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gAgent.sendReliableMessage(); + } +} + +void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) +{ + LLVector3 sitPosition; + LLQuaternion sitRotation; + LLUUID sitObjectID; + BOOL use_autopilot; + mesgsys->getUUIDFast(_PREHASH_SitObject, _PREHASH_ID, sitObjectID); + mesgsys->getBOOLFast(_PREHASH_SitTransform, _PREHASH_AutoPilot, use_autopilot); + mesgsys->getVector3Fast(_PREHASH_SitTransform, _PREHASH_SitPosition, sitPosition); + mesgsys->getQuatFast(_PREHASH_SitTransform, _PREHASH_SitRotation, sitRotation); + LLVector3 camera_eye; + mesgsys->getVector3Fast(_PREHASH_SitTransform, _PREHASH_CameraEyeOffset, camera_eye); + LLVector3 camera_at; + mesgsys->getVector3Fast(_PREHASH_SitTransform, _PREHASH_CameraAtOffset, camera_at); + BOOL force_mouselook; + mesgsys->getBOOLFast(_PREHASH_SitTransform, _PREHASH_ForceMouselook, force_mouselook); + + LLVOAvatar* avatar = gAgent.getAvatarObject(); + + if (avatar && dist_vec_squared(camera_eye, camera_at) > 0.0001f) + { + gAgent.setSitCamera(sitObjectID, camera_eye, camera_at); + } + + gAgent.setForceMouselook(force_mouselook); + + LLViewerObject* object = gObjectList.findObject(sitObjectID); + if (object) + { + LLVector3 sit_spot = object->getPositionAgent() + (sitPosition * object->getRotation()); + if (!use_autopilot || (avatar && avatar->isSitting() && avatar->getRoot() == object->getRoot())) + { + //we're already sitting on this object, so don't autopilot + } + else + { + gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(sit_spot), "Sit", &sitRotation, near_sit_object, NULL, 0.5f); + } + } + else + { + LL_WARNS("Messaging") << "Received sit approval for unknown object " << sitObjectID << LL_ENDL; + } +} + +void process_clear_follow_cam_properties(LLMessageSystem *mesgsys, void **user_data) +{ + LLUUID source_id; + + mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, source_id); + + LLFollowCamMgr::removeFollowCamParams(source_id); +} + +void process_set_follow_cam_properties(LLMessageSystem *mesgsys, void **user_data) +{ + S32 type; + F32 value; + bool settingPosition = false; + bool settingFocus = false; + bool settingFocusOffset = false; + LLVector3 position; + LLVector3 focus; + LLVector3 focus_offset; + + LLUUID source_id; + + mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, source_id); + + LLViewerObject* objectp = gObjectList.findObject(source_id); + if (objectp) + { + objectp->mFlags |= FLAGS_CAMERA_SOURCE; + } + + S32 num_objects = mesgsys->getNumberOfBlocks("CameraProperty"); + for (S32 block_index = 0; block_index < num_objects; block_index++) + { + mesgsys->getS32("CameraProperty", "Type", type, block_index); + mesgsys->getF32("CameraProperty", "Value", value, block_index); + switch(type) + { + case FOLLOWCAM_PITCH: + LLFollowCamMgr::setPitch(source_id, value); + break; + case FOLLOWCAM_FOCUS_OFFSET_X: + focus_offset.mV[VX] = value; + settingFocusOffset = true; + break; + case FOLLOWCAM_FOCUS_OFFSET_Y: + focus_offset.mV[VY] = value; + settingFocusOffset = true; + break; + case FOLLOWCAM_FOCUS_OFFSET_Z: + focus_offset.mV[VZ] = value; + settingFocusOffset = true; + break; + case FOLLOWCAM_POSITION_LAG: + LLFollowCamMgr::setPositionLag(source_id, value); + break; + case FOLLOWCAM_FOCUS_LAG: + LLFollowCamMgr::setFocusLag(source_id, value); + break; + case FOLLOWCAM_DISTANCE: + LLFollowCamMgr::setDistance(source_id, value); + break; + case FOLLOWCAM_BEHINDNESS_ANGLE: + LLFollowCamMgr::setBehindnessAngle(source_id, value); + break; + case FOLLOWCAM_BEHINDNESS_LAG: + LLFollowCamMgr::setBehindnessLag(source_id, value); + break; + case FOLLOWCAM_POSITION_THRESHOLD: + LLFollowCamMgr::setPositionThreshold(source_id, value); + break; + case FOLLOWCAM_FOCUS_THRESHOLD: + LLFollowCamMgr::setFocusThreshold(source_id, value); + break; + case FOLLOWCAM_ACTIVE: + //if 1, set using followcam,. + LLFollowCamMgr::setCameraActive(source_id, value != 0.f); + break; + case FOLLOWCAM_POSITION_X: + settingPosition = true; + position.mV[ 0 ] = value; + break; + case FOLLOWCAM_POSITION_Y: + settingPosition = true; + position.mV[ 1 ] = value; + break; + case FOLLOWCAM_POSITION_Z: + settingPosition = true; + position.mV[ 2 ] = value; + break; + case FOLLOWCAM_FOCUS_X: + settingFocus = true; + focus.mV[ 0 ] = value; + break; + case FOLLOWCAM_FOCUS_Y: + settingFocus = true; + focus.mV[ 1 ] = value; + break; + case FOLLOWCAM_FOCUS_Z: + settingFocus = true; + focus.mV[ 2 ] = value; + break; + case FOLLOWCAM_POSITION_LOCKED: + LLFollowCamMgr::setPositionLocked(source_id, value != 0.f); + break; + case FOLLOWCAM_FOCUS_LOCKED: + LLFollowCamMgr::setFocusLocked(source_id, value != 0.f); + break; + + default: + break; + } + } + + if ( settingPosition ) + { + LLFollowCamMgr::setPosition(source_id, position); + } + if ( settingFocus ) + { + LLFollowCamMgr::setFocus(source_id, focus); + } + if ( settingFocusOffset ) + { + LLFollowCamMgr::setFocusOffset(source_id, focus_offset); + } +} +//end Ventrella + + +// Culled from newsim lltask.cpp +void process_name_value(LLMessageSystem *mesgsys, void **user_data) +{ + std::string temp_str; + LLUUID id; + S32 i, num_blocks; + + mesgsys->getUUIDFast(_PREHASH_TaskData, _PREHASH_ID, id); + + LLViewerObject* object = gObjectList.findObject(id); + + if (object) + { + num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_NameValueData); + for (i = 0; i < num_blocks; i++) + { + mesgsys->getStringFast(_PREHASH_NameValueData, _PREHASH_NVPair, temp_str, i); + LL_INFOS("Messaging") << "Added to object Name Value: " << temp_str << LL_ENDL; + object->addNVPair(temp_str); + } + } + else + { + LL_INFOS("Messaging") << "Can't find object " << id << " to add name value pair" << LL_ENDL; + } +} + +void process_remove_name_value(LLMessageSystem *mesgsys, void **user_data) +{ + std::string temp_str; + LLUUID id; + S32 i, num_blocks; + + mesgsys->getUUIDFast(_PREHASH_TaskData, _PREHASH_ID, id); + + LLViewerObject* object = gObjectList.findObject(id); + + if (object) + { + num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_NameValueData); + for (i = 0; i < num_blocks; i++) + { + mesgsys->getStringFast(_PREHASH_NameValueData, _PREHASH_NVPair, temp_str, i); + LL_INFOS("Messaging") << "Removed from object Name Value: " << temp_str << LL_ENDL; + object->removeNVPair(temp_str); + } + } + else + { + LL_INFOS("Messaging") << "Can't find object " << id << " to remove name value pair" << LL_ENDL; + } +} + +void process_kick_user(LLMessageSystem *msg, void** /*user_data*/) +{ + std::string message; + + msg->getStringFast(_PREHASH_UserInfo, _PREHASH_Reason, message); + + LLAppViewer::instance()->forceDisconnect(message); +} + + +/* +void process_user_list_reply(LLMessageSystem *msg, void **user_data) +{ + LLUserList::processUserListReply(msg, user_data); + return; + char firstname[MAX_STRING+1]; + char lastname[MAX_STRING+1]; + U8 status; + S32 user_count; + + user_count = msg->getNumberOfBlocks("UserBlock"); + + for (S32 i = 0; i < user_count; i++) + { + msg->getData("UserBlock", i, "FirstName", firstname); + msg->getData("UserBlock", i, "LastName", lastname); + msg->getData("UserBlock", i, "Status", &status); + + if (status & 0x01) + { + dialog_friends_add_friend(buffer, TRUE); + } + else + { + dialog_friends_add_friend(buffer, FALSE); + } + } + + dialog_friends_done_adding(); +} +*/ + +// this is not handled in processUpdateMessage +/* +void process_time_dilation(LLMessageSystem *msg, void **user_data) +{ + // get the time_dilation + U16 foo; + msg->getData("TimeDilation", "TimeDilation", &foo); + F32 time_dilation = ((F32) foo) / 65535.f; + + // get the pointer to the right region + U32 ip = msg->getSenderIP(); + U32 port = msg->getSenderPort(); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegion(ip, port); + if (regionp) + { + regionp->setTimeDilation(time_dilation); + } +} +*/ + + + +void process_money_balance_reply( LLMessageSystem* msg, void** ) +{ + S32 balance = 0; + S32 credit = 0; + S32 committed = 0; + std::string desc; + + msg->getS32("MoneyData", "MoneyBalance", balance); + msg->getS32("MoneyData", "SquareMetersCredit", credit); + msg->getS32("MoneyData", "SquareMetersCommitted", committed); + msg->getStringFast(_PREHASH_MoneyData, _PREHASH_Description, desc); + LL_INFOS("Messaging") << "L$, credit, committed: " << balance << " " << credit << " " + << committed << LL_ENDL; + + if (gStatusBar) + { + S32 old_balance = gStatusBar->getBalance(); + + // This is an update, not the first transmission of balance + if (old_balance != 0) + { + // this is actually an update + if (balance > old_balance) + { + LLFirstUse::useBalanceIncrease(balance - old_balance); + } + else if (balance < old_balance) + { + LLFirstUse::useBalanceDecrease(balance - old_balance); + } + } + + gStatusBar->setBalance(balance); + gStatusBar->setLandCredit(credit); + gStatusBar->setLandCommitted(committed); + } + + LLUUID tid; + msg->getUUID("MoneyData", "TransactionID", tid); + static std::deque<LLUUID> recent; + if(!desc.empty() && gSavedSettings.getBOOL("NotifyMoneyChange") + && (std::find(recent.rbegin(), recent.rend(), tid) == recent.rend())) + { + // Make the user confirm the transaction, since they might + // have missed something during an event. + // *TODO: Translate + LLSD args; + args["MESSAGE"] = desc; + LLNotifications::instance().add("SystemMessage", args); + + // Once the 'recent' container gets large enough, chop some + // off the beginning. + const U32 MAX_LOOKBACK = 30; + const S32 POP_FRONT_SIZE = 12; + if(recent.size() > MAX_LOOKBACK) + { + LL_DEBUGS("Messaging") << "Removing oldest transaction records" << LL_ENDL; + recent.erase(recent.begin(), recent.begin() + POP_FRONT_SIZE); + } + //LL_DEBUGS("Messaging") << "Pushing back transaction " << tid << LL_ENDL; + recent.push_back(tid); + } +} + +bool handle_special_notification_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + + if (0 == option) + { + // set the preference to the maturity of the region we're calling + int preferredMaturity = notification["payload"]["_region_access"].asInteger(); + gSavedSettings.setU32("PreferredMaturity", preferredMaturity); + gAgent.sendMaturityPreferenceToServer(preferredMaturity); + + } + + return false; +} + +// some of the server notifications need special handling. This is where we do that. +bool handle_special_notification(std::string notificationID, LLSD& llsdBlock) +{ + int regionAccess = llsdBlock["_region_access"].asInteger(); + llsdBlock["REGIONMATURITY"] = LLViewerRegion::accessToString(regionAccess); + + // we're going to throw the LLSD in there in case anyone ever wants to use it + LLNotifications::instance().add(notificationID+"_Notify", llsdBlock); + + if (regionAccess == SIM_ACCESS_MATURE) + { + if (gAgent.isTeen()) + { + LLNotifications::instance().add(notificationID+"_KB", llsdBlock); + return true; + } + else if (gAgent.prefersPG()) + { + LLNotifications::instance().add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback); + return true; + } + } + else if (regionAccess == SIM_ACCESS_ADULT) + { + if (!gAgent.isAdult()) + { + LLNotifications::instance().add(notificationID+"_KB", llsdBlock); + return true; + } + else if (gAgent.prefersPG() || gAgent.prefersMature()) + { + LLNotifications::instance().add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback); + return true; + } + } + return false; +} + +bool attempt_standard_notification(LLMessageSystem* msgsystem) +{ + // if we have additional alert data + if (msgsystem->has(_PREHASH_AlertInfo) && msgsystem->getNumberOfBlocksFast(_PREHASH_AlertInfo) > 0) + { + // notification was specified using the new mechanism, so we can just handle it here + std::string notificationID; + std::string llsdRaw; + LLSD llsdBlock; + msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, notificationID); + msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_ExtraParams, llsdRaw); + if (llsdRaw.length()) + { + std::istringstream llsdData(llsdRaw); + if (!LLSDSerialize::deserialize(llsdBlock, llsdData, llsdRaw.length())) + { + llwarns << "attempt_standard_notification: Attempted to read notification parameter data into LLSD but failed:" << llsdRaw << llendl; + } + } + + if ( + (notificationID == "RegionEntryAccessBlocked") || + (notificationID == "LandClaimAccessBlocked") || + (notificationID == "LandBuyAccessBlocked") + ) + { + /*--------------------------------------------------------------------- + (Commented so a grep will find the notification strings, since + we construct them on the fly; if you add additional notifications, + please update the comment.) + + Could throw any of the following notifications: + + RegionEntryAccessBlocked + RegionEntryAccessBlocked_Notify + RegionEntryAccessBlocked_Change + RegionEntryAccessBlocked_KB + LandClaimAccessBlocked + LandClaimAccessBlocked_Notify + LandClaimAccessBlocked_Change + LandClaimAccessBlocked_KB + LandBuyAccessBlocked + LandBuyAccessBlocked_Notify + LandBuyAccessBlocked_Change + LandBuyAccessBlocked_KB + + -----------------------------------------------------------------------*/ + if (handle_special_notification(notificationID, llsdBlock)) + { + return true; + } + } + + LLNotifications::instance().add(notificationID, llsdBlock); + return true; + } + return false; +} + + +void process_agent_alert_message(LLMessageSystem* msgsystem, void** user_data) +{ + // make sure the cursor is back to the usual default since the + // alert is probably due to some kind of error. + gViewerWindow->getWindow()->resetBusyCount(); + + if (!attempt_standard_notification(msgsystem)) + { + BOOL modal = FALSE; + msgsystem->getBOOL("AlertData", "Modal", modal); + std::string buffer; + msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer); + process_alert_core(buffer, modal); + } +} + +// The only difference between this routine and the previous is the fact that +// for this routine, the modal parameter is always false. Sadly, for the message +// handled by this routine, there is no "Modal" parameter on the message, and +// there's no API to tell if a message has the given parameter or not. +// So we can't handle the messages with the same handler. +void process_alert_message(LLMessageSystem *msgsystem, void **user_data) +{ + // make sure the cursor is back to the usual default since the + // alert is probably due to some kind of error. + gViewerWindow->getWindow()->resetBusyCount(); + + if (!attempt_standard_notification(msgsystem)) + { + BOOL modal = FALSE; + std::string buffer; + msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer); + process_alert_core(buffer, modal); + } +} + +void process_alert_core(const std::string& message, BOOL modal) +{ + // HACK -- handle callbacks for specific alerts + if ( message == "You died and have been teleported to your home location") + { + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_KILLED_COUNT); + } + else if( message == "Home position set." ) + { + // save the home location image to disk + std::string snap_filename = gDirUtilp->getLindenUserDir(); + snap_filename += gDirUtilp->getDirDelimiter(); + snap_filename += SCREEN_HOME_FILENAME; + gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight(), FALSE, FALSE); + } + + const std::string ALERT_PREFIX("ALERT: "); + const std::string NOTIFY_PREFIX("NOTIFY: "); + if (message.find(ALERT_PREFIX) == 0) + { + // Allow the server to spawn a named alert so that server alerts can be + // translated out of English. + std::string alert_name(message.substr(ALERT_PREFIX.length())); + LLNotifications::instance().add(alert_name); + } + else if (message.find(NOTIFY_PREFIX) == 0) + { + // Allow the server to spawn a named notification so that server notifications can be + // translated out of English. + std::string notify_name(message.substr(NOTIFY_PREFIX.length())); + LLNotifications::instance().add(notify_name); + } + else if (message[0] == '/') + { + // System message is important, show in upper-right box not tip + std::string text(message.substr(1)); + LLSD args; + if (text.substr(0,17) == "RESTART_X_MINUTES") + { + S32 mins = 0; + LLStringUtil::convertToS32(text.substr(18), mins); + args["MINUTES"] = llformat("%d",mins); + LLNotifications::instance().add("RegionRestartMinutes", args); + } + else if (text.substr(0,17) == "RESTART_X_SECONDS") + { + S32 secs = 0; + LLStringUtil::convertToS32(text.substr(18), secs); + args["SECONDS"] = llformat("%d",secs); + LLNotifications::instance().add("RegionRestartSeconds", args); + } + else + { + std::string new_msg =LLNotifications::instance().getGlobalString(text); + args["MESSAGE"] = new_msg; + LLNotifications::instance().add("SystemMessage", args); + } + } + else if (modal) + { + LLSD args; + std::string new_msg =LLNotifications::instance().getGlobalString(message); + args["ERROR_MESSAGE"] = new_msg; + LLNotifications::instance().add("ErrorMessage", args); + } + else + { + LLSD args; + std::string new_msg =LLNotifications::instance().getGlobalString(message); + args["MESSAGE"] = new_msg; + LLNotifications::instance().add("SystemMessageTip", args); + } +} + +mean_collision_list_t gMeanCollisionList; +time_t gLastDisplayedTime = 0; + +void handle_show_mean_events(void *) +{ + if (gNoRender) + { + return; + } + LLFloaterReg::showInstance("bumps"); + //LLFloaterBump::showInstance(); +} + +void mean_name_callback(const LLUUID &id, const std::string& first, const std::string& last, BOOL always_false) +{ + if (gNoRender) + { + return; + } + + static const U32 max_collision_list_size = 20; + if (gMeanCollisionList.size() > max_collision_list_size) + { + mean_collision_list_t::iterator iter = gMeanCollisionList.begin(); + for (U32 i=0; i<max_collision_list_size; i++) iter++; + for_each(iter, gMeanCollisionList.end(), DeletePointer()); + gMeanCollisionList.erase(iter, gMeanCollisionList.end()); + } + + for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin(); + iter != gMeanCollisionList.end(); ++iter) + { + LLMeanCollisionData *mcd = *iter; + if (mcd->mPerp == id) + { + mcd->mFirstName = first; + mcd->mLastName = last; + } + } +} + +void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **user_data) +{ + if (gAgent.inPrelude()) + { + // In prelude, bumping is OK. This dialog is rather confusing to + // newbies, so we don't show it. Drop the packet on the floor. + return; + } + + // make sure the cursor is back to the usual default since the + // alert is probably due to some kind of error. + gViewerWindow->getWindow()->resetBusyCount(); + + LLUUID perp; + U32 time; + U8 u8type; + EMeanCollisionType type; + F32 mag; + + S32 i, num = msgsystem->getNumberOfBlocks(_PREHASH_MeanCollision); + + for (i = 0; i < num; i++) + { + msgsystem->getUUIDFast(_PREHASH_MeanCollision, _PREHASH_Perp, perp); + msgsystem->getU32Fast(_PREHASH_MeanCollision, _PREHASH_Time, time); + msgsystem->getF32Fast(_PREHASH_MeanCollision, _PREHASH_Mag, mag); + msgsystem->getU8Fast(_PREHASH_MeanCollision, _PREHASH_Type, u8type); + + type = (EMeanCollisionType)u8type; + + BOOL b_found = FALSE; + + for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin(); + iter != gMeanCollisionList.end(); ++iter) + { + LLMeanCollisionData *mcd = *iter; + if ((mcd->mPerp == perp) && (mcd->mType == type)) + { + mcd->mTime = time; + mcd->mMag = mag; + b_found = TRUE; + break; + } + } + + if (!b_found) + { + LLMeanCollisionData *mcd = new LLMeanCollisionData(gAgentID, perp, time, type, mag); + gMeanCollisionList.push_front(mcd); + const BOOL is_group = FALSE; + gCacheName->get(perp, is_group, &mean_name_callback); + } + } +} + +void process_frozen_message(LLMessageSystem *msgsystem, void **user_data) +{ + // make sure the cursor is back to the usual default since the + // alert is probably due to some kind of error. + gViewerWindow->getWindow()->resetBusyCount(); + BOOL b_frozen; + + msgsystem->getBOOL("FrozenData", "Data", b_frozen); + + // TODO: make being frozen change view + if (b_frozen) + { + } + else + { + } +} + +// do some extra stuff once we get our economy data +void process_economy_data(LLMessageSystem *msg, void** /*user_data*/) +{ + LLGlobalEconomy::processEconomyData(msg, LLGlobalEconomy::Singleton::getInstance()); + + S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + + LL_INFOS_ONCE("Messaging") << "EconomyData message arrived; upload cost is L$" << upload_cost << LL_ENDL; + + gMenuHolder->childSetLabelArg("Upload Image", "[COST]", llformat("%d", upload_cost)); + gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", llformat("%d", upload_cost)); + gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", llformat("%d", upload_cost)); + gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", llformat("%d", upload_cost)); +} + +void notify_cautioned_script_question(const LLSD& notification, const LLSD& response, S32 orig_questions, BOOL granted) +{ + // only continue if at least some permissions were requested + if (orig_questions) + { + // check to see if the person we are asking + + // "'[OBJECTNAME]', an object owned by '[OWNERNAME]', + // located in [REGIONNAME] at [REGIONPOS], + // has been <granted|denied> permission to: [PERMISSIONS]." + + LLUIString notice(LLTrans::getString(granted ? "ScriptQuestionCautionChatGranted" : "ScriptQuestionCautionChatDenied")); + + // always include the object name and owner name + notice.setArg("[OBJECTNAME]", notification["payload"]["object_name"].asString()); + notice.setArg("[OWNERNAME]", notification["payload"]["owner_name"].asString()); + + // try to lookup viewerobject that corresponds to the object that + // requested permissions (here, taskid->requesting object id) + BOOL foundpos = FALSE; + LLViewerObject* viewobj = gObjectList.findObject(notification["payload"]["task_id"].asUUID()); + if (viewobj) + { + // found the viewerobject, get it's position in its region + LLVector3 objpos(viewobj->getPosition()); + + // try to lookup the name of the region the object is in + LLViewerRegion* viewregion = viewobj->getRegion(); + if (viewregion) + { + // got the region, so include the region and 3d coordinates of the object + notice.setArg("[REGIONNAME]", viewregion->getName()); + std::string formatpos = llformat("%.1f, %.1f,%.1f", objpos[VX], objpos[VY], objpos[VZ]); + notice.setArg("[REGIONPOS]", formatpos); + + foundpos = TRUE; + } + } + + if (!foundpos) + { + // unable to determine location of the object + notice.setArg("[REGIONNAME]", "(unknown region)"); + notice.setArg("[REGIONPOS]", "(unknown position)"); + } + + // check each permission that was requested, and list each + // permission that has been flagged as a caution permission + BOOL caution = FALSE; + S32 count = 0; + std::string perms; + for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++) + { + if ((orig_questions & LSCRIPTRunTimePermissionBits[i]) && SCRIPT_QUESTION_IS_CAUTION[i]) + { + count++; + caution = TRUE; + + // add a comma before the permission description if it is not the first permission + // added to the list or the last permission to check + if ((count > 1) && (i < SCRIPT_PERMISSION_EOF)) + { + perms.append(", "); + } + + perms.append(LLTrans::getString(SCRIPT_QUESTIONS[i])); + } + } + + notice.setArg("[PERMISSIONS]", perms); + + // log a chat message as long as at least one requested permission + // is a caution permission + if (caution) + { + LLChat chat(notice.getString()); + LLFloaterChat::addChat(chat, FALSE, FALSE); + } + } +} + +bool script_question_cb(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + LLMessageSystem *msg = gMessageSystem; + S32 orig = notification["payload"]["questions"].asInteger(); + S32 new_questions = orig; + + // check whether permissions were granted or denied + BOOL allowed = TRUE; + // the "yes/accept" button is the first button in the template, making it button 0 + // if any other button was clicked, the permissions were denied + if (option != 0) + { + new_questions = 0; + allowed = FALSE; + } + + LLUUID task_id = notification["payload"]["task_id"].asUUID(); + LLUUID item_id = notification["payload"]["item_id"].asUUID(); + + // reply with the permissions granted or denied + msg->newMessageFast(_PREHASH_ScriptAnswerYes); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Data); + msg->addUUIDFast(_PREHASH_TaskID, task_id); + msg->addUUIDFast(_PREHASH_ItemID, item_id); + msg->addS32Fast(_PREHASH_Questions, new_questions); + msg->sendReliable(LLHost(notification["payload"]["sender"].asString())); + + // only log a chat message if caution prompts are enabled + if (gSavedSettings.getBOOL("PermissionsCautionEnabled")) + { + // log a chat message, if appropriate + notify_cautioned_script_question(notification, response, orig, allowed); + } + + if ( response["Mute"] ) // mute + { + LLMuteList::getInstance()->add(LLMute(item_id, notification["payload"]["object_name"].asString(), LLMute::OBJECT)); + + // purge the message queue of any previously queued requests from the same source. DEV-4879 + class OfferMatcher : public LLNotifyBoxView::Matcher + { + public: + OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {} + BOOL matches(const LLNotificationPtr notification) const + { + if (notification->getName() == "ScriptQuestionCaution" + || notification->getName() == "ScriptQuestion") + { + return (notification->getPayload()["item_id"].asUUID() == blocked_id); + } + return FALSE; + } + private: + const LLUUID& blocked_id; + }; + // should do this via the channel + gNotifyBoxView->purgeMessagesMatching(OfferMatcher(item_id)); + } + + if (response["Details"]) + { + // respawn notification... + LLNotifications::instance().add(notification["name"], notification["substitutions"], notification["payload"]); + + // ...with description on top + LLNotifications::instance().add("DebitPermissionDetails"); + } + return false; +} +static LLNotificationFunctorRegistration script_question_cb_reg_1("ScriptQuestion", script_question_cb); +static LLNotificationFunctorRegistration script_question_cb_reg_2("ScriptQuestionCaution", script_question_cb); + +void process_script_question(LLMessageSystem *msg, void **user_data) +{ + // *TODO: Translate owner name -> [FIRST] [LAST] + + LLHost sender = msg->getSender(); + + LLUUID taskid; + LLUUID itemid; + S32 questions; + std::string object_name; + std::string owner_name; + + // taskid -> object key of object requesting permissions + msg->getUUIDFast(_PREHASH_Data, _PREHASH_TaskID, taskid ); + // itemid -> script asset key of script requesting permissions + msg->getUUIDFast(_PREHASH_Data, _PREHASH_ItemID, itemid ); + msg->getStringFast(_PREHASH_Data, _PREHASH_ObjectName, object_name); + msg->getStringFast(_PREHASH_Data, _PREHASH_ObjectOwner, owner_name); + msg->getS32Fast(_PREHASH_Data, _PREHASH_Questions, questions ); + + // Special case. If the objects are owned by this agent, throttle per-object instead + // of per-owner. It's common for residents to reset a ton of scripts that re-request + // permissions, as with tier boxes. UUIDs can't be valid agent names and vice-versa, + // so we'll reuse the same namespace for both throttle types. + std::string throttle_name = owner_name; + std::string self_name; + LLAgentUI::buildName( self_name ); + if( owner_name == self_name ) + { + throttle_name = taskid.getString(); + } + + // don't display permission requests if this object is muted + if (LLMuteList::getInstance()->isMuted(taskid)) return; + + // throttle excessive requests from any specific user's scripts + typedef LLKeyThrottle<std::string> LLStringThrottle; + static LLStringThrottle question_throttle( LLREQUEST_PERMISSION_THROTTLE_LIMIT, LLREQUEST_PERMISSION_THROTTLE_INTERVAL ); + + switch (question_throttle.noteAction(throttle_name)) + { + case LLStringThrottle::THROTTLE_NEWLY_BLOCKED: + LL_INFOS("Messaging") << "process_script_question throttled" + << " owner_name:" << owner_name + << LL_ENDL; + // Fall through + + case LLStringThrottle::THROTTLE_BLOCKED: + // Escape altogether until we recover + return; + + case LLStringThrottle::THROTTLE_OK: + break; + } + + std::string script_question; + if (questions) + { + BOOL caution = FALSE; + S32 count = 0; + LLSD args; + args["OBJECTNAME"] = object_name; + args["NAME"] = owner_name; + + // check the received permission flags against each permission + for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++) + { + if (questions & LSCRIPTRunTimePermissionBits[i]) + { + count++; + script_question += " " + LLTrans::getString(SCRIPT_QUESTIONS[i]) + "\n"; + + // check whether permission question should cause special caution dialog + caution |= (SCRIPT_QUESTION_IS_CAUTION[i]); + } + } + args["QUESTIONS"] = script_question; + + LLSD payload; + payload["task_id"] = taskid; + payload["item_id"] = itemid; + payload["sender"] = sender.getIPandPort(); + payload["questions"] = questions; + payload["object_name"] = object_name; + payload["owner_name"] = owner_name; + + // check whether cautions are even enabled or not + if (gSavedSettings.getBOOL("PermissionsCautionEnabled")) + { + // display the caution permissions prompt + LLNotifications::instance().add(caution ? "ScriptQuestionCaution" : "ScriptQuestion", args, payload); + } + else + { + // fall back to default behavior if cautions are entirely disabled + LLNotifications::instance().add("ScriptQuestion", args, payload); + } + + } +} + + +void process_derez_container(LLMessageSystem *msg, void**) +{ + LL_WARNS("Messaging") << "call to deprecated process_derez_container" << LL_ENDL; +} + +void container_inventory_arrived(LLViewerObject* object, + InventoryObjectList* inventory, + S32 serial_num, + void* data) +{ + LL_DEBUGS("Messaging") << "container_inventory_arrived()" << LL_ENDL; + if( gAgent.cameraMouselook() ) + { + gAgent.changeCameraToDefault(); + } + + LLFloaterInventory* view = LLFloaterInventory::getActiveInventory(); + + if (inventory->size() > 2) + { + // create a new inventory category to put this in + LLUUID cat_id; + cat_id = gInventory.createNewCategory(gInventory.getRootFolderID(), + LLAssetType::AT_NONE, + LLTrans::getString("AcquiredItems")); + + InventoryObjectList::const_iterator it = inventory->begin(); + InventoryObjectList::const_iterator end = inventory->end(); + for ( ; it != end; ++it) + { + if ((*it)->getType() != LLAssetType::AT_CATEGORY && + (*it)->getType() != LLAssetType::AT_ROOT_CATEGORY) + { + LLInventoryObject* obj = (LLInventoryObject*)(*it); + LLInventoryItem* item = (LLInventoryItem*)(obj); + LLUUID item_id; + item_id.generate(); + time_t creation_date_utc = time_corrected(); + LLPointer<LLViewerInventoryItem> new_item + = new LLViewerInventoryItem(item_id, + cat_id, + item->getPermissions(), + item->getAssetUUID(), + item->getType(), + item->getInventoryType(), + item->getName(), + item->getDescription(), + LLSaleInfo::DEFAULT, + item->getFlags(), + creation_date_utc); + new_item->updateServer(TRUE); + gInventory.updateItem(new_item); + } + } + gInventory.notifyObservers(); + if(view) + { + view->getPanel()->setSelection(cat_id, TAKE_FOCUS_NO); + } + } + else if (inventory->size() == 2) + { + // we're going to get one fake root category as well as the + // one actual object + InventoryObjectList::iterator it = inventory->begin(); + + if ((*it)->getType() == LLAssetType::AT_CATEGORY || + (*it)->getType() == LLAssetType::AT_ROOT_CATEGORY) + { + ++it; + } + + LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); + LLUUID category = gInventory.findCategoryUUIDForType(item->getType()); + + LLUUID item_id; + item_id.generate(); + time_t creation_date_utc = time_corrected(); + LLPointer<LLViewerInventoryItem> new_item + = new LLViewerInventoryItem(item_id, category, + item->getPermissions(), + item->getAssetUUID(), + item->getType(), + item->getInventoryType(), + item->getName(), + item->getDescription(), + LLSaleInfo::DEFAULT, + item->getFlags(), + creation_date_utc); + new_item->updateServer(TRUE); + gInventory.updateItem(new_item); + gInventory.notifyObservers(); + if(view) + { + view->getPanel()->setSelection(item_id, TAKE_FOCUS_NO); + } + } + + // we've got the inventory, now delete this object if this was a take + BOOL delete_object = (BOOL)(intptr_t)data; + LLViewerRegion *region = gAgent.getRegion(); + if (delete_object && region) + { + gMessageSystem->newMessageFast(_PREHASH_ObjectDelete); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + const U8 NO_FORCE = 0; + gMessageSystem->addU8Fast(_PREHASH_Force, NO_FORCE); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); + gMessageSystem->sendReliable(region->getHost()); + } +} + +// method to format the time. +std::string formatted_time(const time_t& the_time) +{ + std::string dateStr = "["+LLTrans::getString("LTimeWeek")+"] [" + +LLTrans::getString("LTimeMonth")+"] [" + +LLTrans::getString("LTimeDay")+"] [" + +LLTrans::getString("LTimeHour")+"]:[" + +LLTrans::getString("LTimeMin")+"]:[" + +LLTrans::getString("LTimeSec")+"] [" + +LLTrans::getString("LTimeYear")+"]"; + + LLSD substitution; + substitution["datetime"] = (S32) the_time; + LLStringUtil::format (dateStr, substitution); + return dateStr; +} + + +void process_teleport_failed(LLMessageSystem *msg, void**) +{ + std::string reason; + std::string big_reason; + LLSD args; + + // if we have additional alert data + if (msg->has(_PREHASH_AlertInfo) && msg->getSizeFast(_PREHASH_AlertInfo, _PREHASH_Message) > 0) + { + // Get the message ID + msg->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, reason); + big_reason = LLAgent::sTeleportErrorMessages[reason]; + if ( big_reason.size() > 0 ) + { // Substitute verbose reason from the local map + args["REASON"] = big_reason; + } + else + { // Nothing found in the map - use what the server returned in the original message block + msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, reason); + args["REASON"] = reason; + } + + LLSD llsd_block; + std::string llsd_raw; + msg->getStringFast(_PREHASH_AlertInfo, _PREHASH_ExtraParams, llsd_raw); + if (llsd_raw.length()) + { + std::istringstream llsd_data(llsd_raw); + if (!LLSDSerialize::deserialize(llsd_block, llsd_data, llsd_raw.length())) + { + llwarns << "process_teleport_failed: Attempted to read alert parameter data into LLSD but failed:" << llsd_raw << llendl; + } + else + { + // change notification name in this special case + if (handle_special_notification("RegionEntryAccessBlocked", llsd_block)) + { + if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) + { + gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); + } + return; + } + } + } + + } + else + { + msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, reason); + + big_reason = LLAgent::sTeleportErrorMessages[reason]; + if ( big_reason.size() > 0 ) + { // Substitute verbose reason from the local map + args["REASON"] = big_reason; + } + else + { // Nothing found in the map - use what the server returned + args["REASON"] = reason; + } + } + + LLNotifications::instance().add("CouldNotTeleportReason", args); + + // Let the interested parties know that teleport failed. + LLViewerParcelMgr::getInstance()->onTeleportFailed(); + + if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) + { + gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); + } +} + +void process_teleport_local(LLMessageSystem *msg,void**) +{ + LLUUID agent_id; + msg->getUUIDFast(_PREHASH_Info, _PREHASH_AgentID, agent_id); + if (agent_id != gAgent.getID()) + { + LL_WARNS("Messaging") << "Got teleport notification for wrong agent!" << LL_ENDL; + return; + } + + U32 location_id; + LLVector3 pos, look_at; + U32 teleport_flags; + msg->getU32Fast(_PREHASH_Info, _PREHASH_LocationID, location_id); + msg->getVector3Fast(_PREHASH_Info, _PREHASH_Position, pos); + msg->getVector3Fast(_PREHASH_Info, _PREHASH_LookAt, look_at); + msg->getU32Fast(_PREHASH_Info, _PREHASH_TeleportFlags, teleport_flags); + + if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) + { + gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); + } + + // Sim tells us whether the new position is off the ground + if (teleport_flags & TELEPORT_FLAGS_IS_FLYING) + { + gAgent.setFlying(TRUE); + } + else + { + gAgent.setFlying(FALSE); + } + + gAgent.setPositionAgent(pos); + gAgent.slamLookAt(look_at); + + // likewise make sure the camera is behind the avatar + gAgent.resetView(TRUE, TRUE); + + // send camera update to new region + gAgent.updateCamera(); + + send_agent_update(TRUE, TRUE); + + // Let the interested parties know we've teleported. + // Vadim *HACK: Agent position seems to get reset (to render position?) + // on each frame, so we have to pass the new position manually. + LLViewerParcelMgr::getInstance()->onTeleportFinished(true, gAgent.getPosGlobalFromAgent(pos)); +} + +void send_simple_im(const LLUUID& to_id, + const std::string& message, + EInstantMessage dialog, + const LLUUID& id) +{ + std::string my_name; + LLAgentUI::buildFullname(my_name); + send_improved_im(to_id, + my_name, + message, + IM_ONLINE, + dialog, + id, + NO_TIMESTAMP, + (U8*)EMPTY_BINARY_BUCKET, + EMPTY_BINARY_BUCKET_SIZE); +} + +void send_group_notice(const LLUUID& group_id, + const std::string& subject, + const std::string& message, + const LLInventoryItem* item) +{ + // Put this notice into an instant message form. + // This will mean converting the item to a binary bucket, + // and the subject/message into a single field. + std::string my_name; + LLAgentUI::buildFullname(my_name); + + // Combine subject + message into a single string. + std::ostringstream subject_and_message; + // TODO: turn all existing |'s into ||'s in subject and message. + subject_and_message << subject << "|" << message; + + // Create an empty binary bucket. + U8 bin_bucket[MAX_INVENTORY_BUFFER_SIZE]; + U8* bucket_to_send = bin_bucket; + bin_bucket[0] = '\0'; + S32 bin_bucket_size = EMPTY_BINARY_BUCKET_SIZE; + // If there is an item being sent, pack it into the binary bucket. + if (item) + { + LLSD item_def; + item_def["item_id"] = item->getUUID(); + item_def["owner_id"] = item->getPermissions().getOwner(); + std::ostringstream ostr; + LLSDSerialize::serialize(item_def, ostr, LLSDSerialize::LLSD_XML); + bin_bucket_size = ostr.str().copy( + (char*)bin_bucket, ostr.str().size()); + bin_bucket[bin_bucket_size] = '\0'; + } + else + { + bucket_to_send = (U8*) EMPTY_BINARY_BUCKET; + } + + + send_improved_im( + group_id, + my_name, + subject_and_message.str(), + IM_ONLINE, + IM_GROUP_NOTICE, + LLUUID::null, + NO_TIMESTAMP, + bucket_to_send, + bin_bucket_size); +} + +bool handle_lure_callback(const LLSD& notification, const LLSD& response) +{ + std::string text = response["message"].asString(); + S32 option = LLNotification::getSelectedOption(notification, response); + + if(0 == option) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_StartLure); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Info); + msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in. + msg->addStringFast(_PREHASH_Message, text); + for(LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray(); + it != notification["payload"]["ids"].endArray(); + ++it) + { + msg->nextBlockFast(_PREHASH_TargetData); + msg->addUUIDFast(_PREHASH_TargetID, it->asUUID()); + } + gAgent.sendReliableMessage(); + } + + return false; +} + +void handle_lure(const LLUUID& invitee) +{ + LLDynamicArray<LLUUID> ids; + ids.push_back(invitee); + handle_lure(ids); +} + +// Prompt for a message to the invited user. +void handle_lure(const std::vector<LLUUID>& ids) +{ + LLSD edit_args; + edit_args["REGION"] = gAgent.getRegion()->getName(); + + LLSD payload; + for (LLDynamicArray<LLUUID>::const_iterator it = ids.begin(); + it != ids.end(); + ++it) + { + payload["ids"].append(*it); + } + if (gAgent.isGodlike()) + { + LLNotifications::instance().add("OfferTeleportFromGod", edit_args, payload, handle_lure_callback); + } + else + { + LLNotifications::instance().add("OfferTeleport", edit_args, payload, handle_lure_callback); + } +} + + +void send_improved_im(const LLUUID& to_id, + const std::string& name, + const std::string& message, + U8 offline, + EInstantMessage dialog, + const LLUUID& id, + U32 timestamp, + const U8* binary_bucket, + S32 binary_bucket_size) +{ + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + to_id, + name, + message, + offline, + dialog, + id, + 0, + LLUUID::null, + gAgent.getPositionAgent(), + timestamp, + binary_bucket, + binary_bucket_size); + gAgent.sendReliableMessage(); +} + + +void send_places_query(const LLUUID& query_id, + const LLUUID& trans_id, + const std::string& query_text, + U32 query_flags, + S32 category, + const std::string& sim_name) +{ + LLMessageSystem* msg = gMessageSystem; + + msg->newMessage("PlacesQuery"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->addUUID("QueryID", query_id); + msg->nextBlock("TransactionData"); + msg->addUUID("TransactionID", trans_id); + msg->nextBlock("QueryData"); + msg->addString("QueryText", query_text); + msg->addU32("QueryFlags", query_flags); + msg->addS8("Category", (S8)category); + msg->addString("SimName", sim_name); + gAgent.sendReliableMessage(); +} + + +void process_user_info_reply(LLMessageSystem* msg, void**) +{ + LLUUID agent_id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); + if(agent_id != gAgent.getID()) + { + LL_WARNS("Messaging") << "process_user_info_reply - " + << "wrong agent id." << LL_ENDL; + } + + BOOL im_via_email; + msg->getBOOLFast(_PREHASH_UserData, _PREHASH_IMViaEMail, im_via_email); + std::string email; + msg->getStringFast(_PREHASH_UserData, _PREHASH_EMail, email); + std::string dir_visibility; + msg->getString( "UserData", "DirectoryVisibility", dir_visibility); + + LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email, email); + LLFloaterPostcard::updateUserInfo(email); +} + + +//--------------------------------------------------------------------------- +// Script Dialog +//--------------------------------------------------------------------------- + +const S32 SCRIPT_DIALOG_MAX_BUTTONS = 12; +const S32 SCRIPT_DIALOG_BUTTON_STR_SIZE = 24; +const S32 SCRIPT_DIALOG_MAX_MESSAGE_SIZE = 512; +const char* SCRIPT_DIALOG_HEADER = "Script Dialog:\n"; + +bool callback_script_dialog(const LLSD& notification, const LLSD& response) +{ + LLNotificationForm form(notification["form"]); + std::string button = LLNotification::getSelectedOptionName(response); + S32 button_idx = LLNotification::getSelectedOption(notification, response); + // Didn't click "Ignore" + if (button_idx != -1) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("ScriptDialogReply"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->nextBlock("Data"); + msg->addUUID("ObjectID", notification["payload"]["object_id"].asUUID()); + msg->addS32("ChatChannel", notification["payload"]["chat_channel"].asInteger()); + msg->addS32("ButtonIndex", button_idx); + msg->addString("ButtonLabel", button); + msg->sendReliable(LLHost(notification["payload"]["sender"].asString())); + } + + return false; +} +static LLNotificationFunctorRegistration callback_script_dialog_reg_1("ScriptDialog", callback_script_dialog); +static LLNotificationFunctorRegistration callback_script_dialog_reg_2("ScriptDialogGroup", callback_script_dialog); + +void process_script_dialog(LLMessageSystem* msg, void**) +{ + S32 i; + LLSD payload; + + LLUUID object_id; + msg->getUUID("Data", "ObjectID", object_id); + + if (LLMuteList::getInstance()->isMuted(object_id)) + { + return; + } + + std::string message; + std::string first_name; + std::string last_name; + std::string title; + + S32 chat_channel; + msg->getString("Data", "FirstName", first_name); + msg->getString("Data", "LastName", last_name); + msg->getString("Data", "ObjectName", title); + msg->getString("Data", "Message", message); + msg->getS32("Data", "ChatChannel", chat_channel); + + // unused for now + LLUUID image_id; + msg->getUUID("Data", "ImageID", image_id); + + payload["sender"] = msg->getSender().getIPandPort(); + payload["object_id"] = object_id; + payload["chat_channel"] = chat_channel; + + // build up custom form + S32 button_count = msg->getNumberOfBlocks("Buttons"); + if (button_count > SCRIPT_DIALOG_MAX_BUTTONS) + { + llwarns << "Too many script dialog buttons - omitting some" << llendl; + button_count = SCRIPT_DIALOG_MAX_BUTTONS; + } + + LLNotificationForm form; + for (i = 0; i < button_count; i++) + { + std::string tdesc; + msg->getString("Buttons", "ButtonLabel", tdesc, i); + form.addElement("button", std::string(tdesc)); + } + + LLSD args; + args["TITLE"] = title; + args["MESSAGE"] = message; + LLNotificationPtr notification; + if (!first_name.empty()) + { + args["FIRST"] = first_name; + args["LAST"] = last_name; + notification = LLNotifications::instance().add( + LLNotification::Params("ScriptDialog").substitutions(args).payload(payload).form_elements(form.asLLSD())); + } + else + { + args["GROUPNAME"] = last_name; + notification = LLNotifications::instance().add( + LLNotification::Params("ScriptDialogGroup").substitutions(args).payload(payload).form_elements(form.asLLSD())); + } +} + +//--------------------------------------------------------------------------- + + +std::vector<LLSD> gLoadUrlList; + +bool callback_load_url(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + + if (0 == option) + { + LLWeb::loadURL(notification["payload"]["url"].asString()); + } + + return false; +} +static LLNotificationFunctorRegistration callback_load_url_reg("LoadWebPage", callback_load_url); + + +// We've got the name of the person who owns the object hurling the url. +// Display confirmation dialog. +void callback_load_url_name(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group) +{ + std::vector<LLSD>::iterator it; + for (it = gLoadUrlList.begin(); it != gLoadUrlList.end(); ) + { + LLSD load_url_info = *it; + if (load_url_info["owner_id"].asUUID() == id) + { + it = gLoadUrlList.erase(it); + + std::string owner_name; + if (is_group) + { + owner_name = first + LLTrans::getString("Group"); + } + else + { + owner_name = first + " " + last; + } + + // For legacy name-only mutes. + if (LLMuteList::getInstance()->isMuted(LLUUID::null, owner_name)) + { + continue; + } + LLSD args; + args["URL"] = load_url_info["url"].asString(); + args["MESSAGE"] = load_url_info["message"].asString();; + args["OBJECTNAME"] = load_url_info["object_name"].asString(); + args["NAME"] = owner_name; + + LLNotifications::instance().add("LoadWebPage", args, load_url_info); + } + else + { + ++it; + } + } +} + +void process_load_url(LLMessageSystem* msg, void**) +{ + LLUUID object_id; + LLUUID owner_id; + BOOL owner_is_group; + char object_name[256]; /* Flawfinder: ignore */ + char message[256]; /* Flawfinder: ignore */ + char url[256]; /* Flawfinder: ignore */ + + msg->getString("Data", "ObjectName", 256, object_name); + msg->getUUID( "Data", "ObjectID", object_id); + msg->getUUID( "Data", "OwnerID", owner_id); + msg->getBOOL( "Data", "OwnerIsGroup", owner_is_group); + msg->getString("Data", "Message", 256, message); + msg->getString("Data", "URL", 256, url); + + LLSD payload; + payload["object_id"] = object_id; + payload["owner_id"] = owner_id; + payload["owner_is_group"] = owner_is_group; + payload["object_name"] = object_name; + payload["message"] = message; + payload["url"] = url; + + // URL is safety checked in load_url above + + // Check if object or owner is muted + if (LLMuteList::getInstance()->isMuted(object_id, object_name) || + LLMuteList::getInstance()->isMuted(owner_id)) + { + LL_INFOS("Messaging")<<"Ignoring load_url from muted object/owner."<<LL_ENDL; + return; + } + + // Add to list of pending name lookups + gLoadUrlList.push_back(payload); + + gCacheName->get(owner_id, owner_is_group, &callback_load_url_name); +} + + +void callback_download_complete(void** data, S32 result, LLExtStat ext_status) +{ + std::string* filepath = (std::string*)data; + LLSD args; + args["DOWNLOAD_PATH"] = *filepath; + LLNotifications::instance().add("FinishedRawDownload", args); + delete filepath; +} + + +void process_initiate_download(LLMessageSystem* msg, void**) +{ + LLUUID agent_id; + msg->getUUID("AgentData", "AgentID", agent_id); + if (agent_id != gAgent.getID()) + { + LL_WARNS("Messaging") << "Initiate download for wrong agent" << LL_ENDL; + return; + } + + std::string sim_filename; + std::string viewer_filename; + msg->getString("FileData", "SimFilename", sim_filename); + msg->getString("FileData", "ViewerFilename", viewer_filename); + + if (!gXferManager->validateFileForRequest(viewer_filename)) + { + llwarns << "SECURITY: Unauthorized download to local file " << viewer_filename << llendl; + return; + } + gXferManager->requestFile(viewer_filename, + sim_filename, + LL_PATH_NONE, + msg->getSender(), + FALSE, // don't delete remote + callback_download_complete, + (void**)new std::string(viewer_filename)); +} + + +void process_script_teleport_request(LLMessageSystem* msg, void**) +{ + std::string object_name; + std::string sim_name; + LLVector3 pos; + LLVector3 look_at; + + msg->getString("Data", "ObjectName", object_name); + msg->getString("Data", "SimName", sim_name); + msg->getVector3("Data", "SimPosition", pos); + msg->getVector3("Data", "LookAt", look_at); + + LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance(); + if(instance) + { + instance->trackURL( + sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]); + LLFloaterReg::showInstance("world_map", "center"); + } + + // remove above two lines and replace with below line + // to re-enable parcel browser for llMapDestination() + // LLURLDispatcher::dispatch(LLSLURL::buildSLURL(sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]), FALSE); + +} + +void process_covenant_reply(LLMessageSystem* msg, void**) +{ + LLUUID covenant_id, estate_owner_id; + std::string estate_name; + U32 covenant_timestamp; + msg->getUUID("Data", "CovenantID", covenant_id); + msg->getU32("Data", "CovenantTimestamp", covenant_timestamp); + msg->getString("Data", "EstateName", estate_name); + msg->getUUID("Data", "EstateOwnerID", estate_owner_id); + + LLPanelEstateCovenant::updateEstateName(estate_name); + LLPanelLandCovenant::updateEstateName(estate_name); + LLFloaterBuyLand::updateEstateName(estate_name); + + std::string owner_name = + LLSLURL::buildCommand("agent", estate_owner_id, "inspect"); + LLPanelEstateCovenant::updateEstateOwnerName(owner_name); + LLPanelLandCovenant::updateEstateOwnerName(owner_name); + LLFloaterBuyLand::updateEstateOwnerName(owner_name); + + LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info"); + if (panel) + { + panel->updateEstateName(estate_name); + panel->updateEstateOwnerName(owner_name); + } + + // standard message, not from system + std::string last_modified; + if (covenant_timestamp == 0) + { + last_modified = LLTrans::getString("covenant_last_modified")+LLTrans::getString("never_text"); + } + else + { + last_modified = LLTrans::getString("covenant_last_modified")+"[" + +LLTrans::getString("LTimeWeek")+"] [" + +LLTrans::getString("LTimeMonth")+"] [" + +LLTrans::getString("LTimeDay")+"] [" + +LLTrans::getString("LTimeHour")+"]:[" + +LLTrans::getString("LTimeMin")+"]:[" + +LLTrans::getString("LTimeSec")+"] [" + +LLTrans::getString("LTimeYear")+"]"; + LLSD substitution; + substitution["datetime"] = (S32) covenant_timestamp; + LLStringUtil::format (last_modified, substitution); + } + + LLPanelEstateCovenant::updateLastModified(last_modified); + LLPanelLandCovenant::updateLastModified(last_modified); + LLFloaterBuyLand::updateLastModified(last_modified); + + // load the actual covenant asset data + const BOOL high_priority = TRUE; + if (covenant_id.notNull()) + { + gAssetStorage->getEstateAsset(gAgent.getRegionHost(), + gAgent.getID(), + gAgent.getSessionID(), + covenant_id, + LLAssetType::AT_NOTECARD, + ET_Covenant, + onCovenantLoadComplete, + NULL, + high_priority); + } + else + { + std::string covenant_text; + if (estate_owner_id.isNull()) + { + // mainland + covenant_text = LLTrans::getString("RegionNoCovenant"); + } + else + { + covenant_text = LLTrans::getString("RegionNoCovenantOtherOwner"); + } + LLPanelEstateCovenant::updateCovenantText(covenant_text, covenant_id); + LLPanelLandCovenant::updateCovenantText(covenant_text); + LLFloaterBuyLand::updateCovenantText(covenant_text, covenant_id); + if (panel) + { + panel->updateCovenantText(covenant_text); + } + } +} + +void onCovenantLoadComplete(LLVFS *vfs, + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status) +{ + LL_DEBUGS("Messaging") << "onCovenantLoadComplete()" << LL_ENDL; + std::string covenant_text; + if(0 == status) + { + LLVFile file(vfs, asset_uuid, type, LLVFile::READ); + + S32 file_length = file.getSize(); + + std::vector<char> buffer(file_length+1); + file.read((U8*)&buffer[0], file_length); + // put a EOS at the end + buffer[file_length] = '\0'; + + if( (file_length > 19) && !strncmp( &buffer[0], "Linden text version", 19 ) ) + { + LLViewerTextEditor::Params params; + params.name("temp"); + params.max_text_length(file_length+1); + LLViewerTextEditor * editor = LLUICtrlFactory::create<LLViewerTextEditor> (params); + if( !editor->importBuffer( &buffer[0], file_length+1 ) ) + { + LL_WARNS("Messaging") << "Problem importing estate covenant." << LL_ENDL; + covenant_text = "Problem importing estate covenant."; + } + else + { + // Version 0 (just text, doesn't include version number) + covenant_text = editor->getText(); + } + delete editor; + } + else + { + LL_WARNS("Messaging") << "Problem importing estate covenant: Covenant file format error." << LL_ENDL; + covenant_text = "Problem importing estate covenant: Covenant file format error."; + } + } + else + { + LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); + + if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || + LL_ERR_FILE_EMPTY == status) + { + covenant_text = "Estate covenant notecard is missing from database."; + } + else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) + { + covenant_text = "Insufficient permissions to view estate covenant."; + } + else + { + covenant_text = "Unable to load estate covenant at this time."; + } + + LL_WARNS("Messaging") << "Problem loading notecard: " << status << LL_ENDL; + } + LLPanelEstateCovenant::updateCovenantText(covenant_text, asset_uuid); + LLPanelLandCovenant::updateCovenantText(covenant_text); + LLFloaterBuyLand::updateCovenantText(covenant_text, asset_uuid); + + LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info"); + if (panel) + { + panel->updateCovenantText(covenant_text); + } +} + + +void process_feature_disabled_message(LLMessageSystem* msg, void**) +{ + // Handle Blacklisted feature simulator response... + LLUUID agentID; + LLUUID transactionID; + std::string messageText; + msg->getStringFast(_PREHASH_FailureInfo,_PREHASH_ErrorMessage, messageText,0); + msg->getUUIDFast(_PREHASH_FailureInfo,_PREHASH_AgentID,agentID); + msg->getUUIDFast(_PREHASH_FailureInfo,_PREHASH_TransactionID,transactionID); + + LL_WARNS("Messaging") << "Blacklisted Feature Response:" << messageText << LL_ENDL; +} + +// ------------------------------------------------------------ +// Message system exception callbacks +// ------------------------------------------------------------ + +void invalid_message_callback(LLMessageSystem* msg, + void*, + EMessageException exception) +{ + LLAppViewer::instance()->badNetworkHandler(); +} + +// Please do not add more message handlers here. This file is huge. +// Put them in a file related to the functionality you are implementing. + +void LLOfferInfo::forceResponse(InventoryOfferResponse response) +{ + LLNotification::Params params("UserGiveItem"); + params.functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, this, _1, _2)); + LLNotifications::instance().forceResponse(params, response); +} diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 65994dfb30..5c40f2a540 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -44,6 +44,9 @@ #include "llinventory.h" #include "llinventorybridge.h" #include "llinventorymodel.h" +#include "lllandmark.h" +#include "lllandmarkactions.h" +#include "lllandmarklist.h" #include "llmemorystream.h" #include "llmenugl.h" #include "llnotecard.h" @@ -64,10 +67,47 @@ #include "llviewertexturelist.h" #include "llviewerwindow.h" -#include "llappviewer.h" // for gPacificDaylightTime - static LLDefaultChildRegistry::Register<LLViewerTextEditor> r("text_editor"); +///----------------------------------------------------------------------- +/// Class LLEmbeddedLandmarkCopied +///----------------------------------------------------------------------- +class LLEmbeddedLandmarkCopied: public LLInventoryCallback +{ +public: + + LLEmbeddedLandmarkCopied(){} + void fire(const LLUUID& inv_item) + { + showInfo(inv_item); + } + static void showInfo(const LLUUID& landmark_inv_id) + { + LLSD key; + key["type"] = "landmark"; + key["id"] = landmark_inv_id; + LLSideTray::getInstance()->showPanel("panel_places", key); + } + static void processForeignLandmark(LLLandmark* landmark, + const LLUUID& object_id, const LLUUID& notecard_inventory_id, + LLInventoryItem* item) + { + LLVector3d global_pos; + landmark->getGlobalPos(global_pos); + LLViewerInventoryItem* agent_lanmark = + LLLandmarkActions::findLandmarkForGlobalPos(global_pos); + + if (agent_lanmark) + { + showInfo(agent_lanmark->getUUID()); + } + else + { + LLPointer<LLEmbeddedLandmarkCopied> cb = new LLEmbeddedLandmarkCopied(); + copy_inventory_from_notecard(object_id, notecard_inventory_id, item, gInventoryCallbacks.registerCB(cb)); + } + } +}; ///---------------------------------------------------------------------------- /// Class LLEmbeddedNotecardOpener ///---------------------------------------------------------------------------- @@ -1099,14 +1139,12 @@ void LLViewerTextEditor::openEmbeddedLandmark( LLInventoryItem* item, llwchar wc if (!item) return; - LLSD key; - key["type"] = "landmark"; - key["id"] = item->getUUID(); - - LLPanelPlaces *panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->showPanel("panel_places", key)); - if (panel) + LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID(), + boost::bind(&LLEmbeddedLandmarkCopied::processForeignLandmark, _1, mObjectID, mNotecardInventoryID, item)); + if (landmark) { - panel->setItem(item); + LLEmbeddedLandmarkCopied::processForeignLandmark(landmark, mObjectID, + mNotecardInventoryID, item); } } diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index e5c53c91c9..758bf8c1aa 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -93,6 +93,7 @@ BOOL LLViewerTexture::sUseTextureAtlas = FALSE ; const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by const F32 desired_discard_bias_max = 1.5f; // max number of levels to reduce image quality by +const F64 log_2 = log(2.0); //---------------------------------------------------------------------------------------------- //namespace: LLViewerTextureAccess @@ -134,7 +135,7 @@ LLViewerMediaTexture* LLViewerTextureManager::getMediaTexture(const LLUUID& id, return tex ; } -LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLViewerTexture* tex, BOOL report_error) +LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLTexture* tex, BOOL report_error) { if(!tex) { @@ -415,6 +416,7 @@ void LLViewerTexture::init(bool firstinit) mDontDiscard = FALSE; mMaxVirtualSize = 0.f; mNeedsResetMaxVirtualSize = FALSE ; + mParcelMedia = NULL ; } //virtual @@ -522,6 +524,12 @@ F32 LLViewerTexture::getMaxVirtualSize() return mMaxVirtualSize ; } +//virtual +void LLViewerTexture::setKnownDrawSize(S32 width, S32 height) +{ + //nothing here. +} + //virtual void LLViewerTexture::addFace(LLFace* facep) { @@ -852,6 +860,7 @@ void LLViewerFetchedTexture::init(bool firstinit) mKnownDrawWidth = 0; mKnownDrawHeight = 0; + mKnownDrawSizeChanged = FALSE ; if (firstinit) { @@ -1084,10 +1093,17 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) } // Call with 0,0 to turn this feature off. +//virtual void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height) { - mKnownDrawWidth = width; - mKnownDrawHeight = height; + if(mKnownDrawWidth != width || mKnownDrawHeight != height) + { + mKnownDrawWidth = width; + mKnownDrawHeight = height; + + mKnownDrawSizeChanged = TRUE ; + mFullyLoaded = FALSE ; + } addTextureStats((F32)(width * height)); } @@ -1104,13 +1120,26 @@ void LLViewerFetchedTexture::processTextureStats() mDesiredDiscardLevel = getMaxDiscardLevel() ; } else - { - mDesiredDiscardLevel = 0; - if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) + { + if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight) { - mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) + { + mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + } + else + { + mDesiredDiscardLevel = 0; + } } - + else if(mKnownDrawSizeChanged)//known draw size is set + { + mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2, + log((F32)mFullHeight / mKnownDrawHeight) / log_2) ; + mDesiredDiscardLevel = llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ; + } + mKnownDrawSizeChanged = FALSE ; + if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel)) { mFullyLoaded = TRUE ; @@ -1121,8 +1150,6 @@ void LLViewerFetchedTexture::processTextureStats() //texture does not have any data, so we don't know the size of the image, treat it like 32 * 32. F32 LLViewerFetchedTexture::calcDecodePriorityForUnknownTexture(F32 pixel_priority) { - static const F64 log_2 = log(2.0); - F32 desired = (F32)(log(32.0/pixel_priority) / log_2); S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired + 1; ddiscard = llclamp(ddiscard, 1, 9); @@ -1169,7 +1196,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority() // Don't decode anything we don't need priority = -1.0f; } - else if (mBoostLevel == LLViewerTexture::BOOST_UI && !have_all_data) + else if ((mBoostLevel == LLViewerTexture::BOOST_UI || mBoostLevel == LLViewerTexture::BOOST_ICON) && !have_all_data) { priority = 1.f; } @@ -2121,22 +2148,29 @@ void LLViewerMediaTexture::updateClass() { static const F32 MAX_INACTIVE_TIME = 30.f ; +#if 0 + //force to play media. + gSavedSettings.setBOOL("AudioSteamingMedia", true) ; + gSavedSettings.setBOOL("AudioStreamingVideo", true) ; +#endif + for(media_map_t::iterator iter = sMediaMap.begin() ; iter != sMediaMap.end(); ) { LLViewerMediaTexture* mediap = iter->second; - - // - //Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture. - // - if(mediap->getNumRefs() == 1 && mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) //one by sMediaMap - { - media_map_t::iterator cur = iter++ ; - sMediaMap.erase(cur) ; - } - else + + if(mediap->getNumRefs() == 1) //one reference by sMediaMap { - ++iter ; + // + //Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture. + // + if(mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) + { + media_map_t::iterator cur = iter++ ; + sMediaMap.erase(cur) ; + continue ; + } } + ++iter ; } } @@ -2189,11 +2223,22 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL mIsPlaying = FALSE ; setMediaImpl() ; + + LLViewerTexture* tex = gTextureList.findImage(mID) ; + if(tex) //this media is a parcel media for tex. + { + tex->setParcelMedia(this) ; + } } //virtual LLViewerMediaTexture::~LLViewerMediaTexture() { + LLViewerTexture* tex = gTextureList.findImage(mID) ; + if(tex) //this media is a parcel media for tex. + { + tex->setParcelMedia(NULL) ; + } } void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */) @@ -2244,10 +2289,9 @@ BOOL LLViewerMediaTexture::findFaces() mMediaFaceList.clear() ; BOOL ret = TRUE ; - - //for parcel media - LLViewerTexture* tex = gTextureList.findImage(mID) ; - if(tex) + + LLViewerTexture* tex = gTextureList.findImage(mID) ; + 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) @@ -2358,7 +2402,7 @@ void LLViewerMediaTexture::addFace(LLFace* facep) mTextureList.push_back(facep->getTexture()) ; //a parcel media. return ; } - + llerrs << "The face does not have a valid texture before media texture." << llendl ; } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 480e1c1cbc..020478beef 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -163,6 +163,7 @@ public: S32 getFullWidth() const { return mFullWidth; } S32 getFullHeight() const { return mFullHeight; } + /*virtual*/ void setKnownDrawSize(S32 width, S32 height); virtual void addFace(LLFace* facep) ; virtual void removeFace(LLFace* facep) ; @@ -220,6 +221,10 @@ public: BOOL getDontDiscard() const { return mDontDiscard; } //----------------- + void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;} + BOOL hasParcelMedia() const { return mParcelMedia != NULL;} + LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;} + /*virtual*/ void updateBindStatsForTester() ; protected: void cleanup() ; @@ -246,6 +251,9 @@ protected: LLPointer<LLImageGL> mGLTexturep ; S8 mDontDiscard; // Keep full res version of this image (for UI, etc) + //do not use LLPointer here. + LLViewerMediaTexture* mParcelMedia ; + protected: typedef enum { @@ -357,7 +365,7 @@ public: // Override the computation of discard levels if we know the exact output // size of the image. Used for UI textures to not decode, even if we have // more data. - void setKnownDrawSize(S32 width, S32 height); + /*virtual*/ void setKnownDrawSize(S32 width, S32 height); void setIsMissingAsset(); /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; } @@ -406,6 +414,8 @@ private: BOOL mFullyLoaded; protected: + std::string mLocalFileName; + S32 mOrigWidth; S32 mOrigHeight; @@ -413,8 +423,7 @@ protected: // Used for UI textures to not decode, even if we have more data. S32 mKnownDrawWidth; S32 mKnownDrawHeight; - - std::string mLocalFileName; + BOOL mKnownDrawSizeChanged ; S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have @@ -570,7 +579,7 @@ public: static LLTexturePipelineTester* sTesterp ; //returns NULL if tex is not a LLViewerFetchedTexture nor derived from LLViewerFetchedTexture. - static LLViewerFetchedTexture* staticCastToFetchedTexture(LLViewerTexture* tex, BOOL report_error = FALSE) ; + static LLViewerFetchedTexture* staticCastToFetchedTexture(LLTexture* tex, BOOL report_error = FALSE) ; // //"find-texture" just check if the texture exists, if yes, return it, otherwise return null. diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index b0b69fbae6..b574a9c110 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1518,11 +1518,12 @@ void LLViewerWindow::initWorldUI() getRootView()->addChild(gMorphView); // Make space for nav bar. + LLNavigationBar* navbar = LLNavigationBar::getInstance(); LLRect floater_view_rect = gFloaterView->getRect(); LLRect notify_view_rect = gNotifyBoxView->getRect(); - floater_view_rect.mTop -= NAVIGATION_BAR_HEIGHT; + floater_view_rect.mTop -= navbar->getDefNavBarHeight(); floater_view_rect.mBottom += LLBottomTray::getInstance()->getRect().getHeight(); - notify_view_rect.mTop -= NAVIGATION_BAR_HEIGHT; + notify_view_rect.mTop -= navbar->getDefNavBarHeight(); notify_view_rect.mBottom += LLBottomTray::getInstance()->getRect().getHeight(); gFloaterView->setRect(floater_view_rect); gNotifyBoxView->setRect(notify_view_rect); @@ -1549,20 +1550,19 @@ void LLViewerWindow::initWorldUI() gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() ); // Navigation bar - - LLNavigationBar* navbar = LLNavigationBar::getInstance(); navbar->reshape(root_rect.getWidth(), navbar->getRect().getHeight(), TRUE); // *TODO: redundant? navbar->translate(0, root_rect.getHeight() - menu_bar_height - navbar->getRect().getHeight()); // FIXME navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get()); + if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel")) { - navbar->showNavigationPanel(FALSE); + toggle_show_navigation_panel(LLSD(0)); } if (!gSavedSettings.getBOOL("ShowNavbarFavoritesPanel")) { - navbar->showFavoritesPanel(FALSE); + toggle_show_favorites_panel(LLSD(0)); } if (!gSavedSettings.getBOOL("ShowCameraButton")) @@ -2424,19 +2424,35 @@ void LLViewerWindow::updateUI() BOOL handled_by_top_ctrl = FALSE; LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); + LLView* captor_view = dynamic_cast<LLView*>(mouse_captor); + + //FIXME: only include captor and captor's ancestors if mouse is truly over them --RN //build set of views containing mouse cursor by traversing UI hierarchy and testing //screen rect against mouse cursor view_handle_set_t mouse_hover_set; - // start at current mouse captor (if is a view) or UI root - LLView* root_view = NULL; - root_view = dynamic_cast<LLView*>(mouse_captor); + // constraint mouse enter events to children of mouse captor + LLView* root_view = captor_view; + + // if mouse captor doesn't exist or isn't a LLView + // then allow mouse enter events on entire UI hierarchy if (!root_view) { root_view = mRootView; } + // include all ancestors of captor_view as automatically having mouse + if (captor_view) + { + LLView* captor_parent_view = captor_view->getParent(); + while(captor_parent_view) + { + mouse_hover_set.insert(captor_parent_view->getHandle()); + captor_parent_view = captor_parent_view->getParent(); + } + } + // aggregate visible views that contain mouse cursor in display order // while the top_ctrl contains the mouse cursor, only it and its descendants will receive onMouseEnter events diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index f9c95afc31..4bf66ba17e 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2448,28 +2448,20 @@ void LLVOAvatar::idleUpdateAppearanceAnimation() } else { - F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME); - F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME); - F32 morph_amt; - if (last_blend_frac == 1.f) - { - morph_amt = 1.f; - } - else - { - morph_amt = (blend_frac - last_blend_frac) / (1.f - last_blend_frac); - } - + F32 morph_amt = calcMorphAmount(); LLVisualParam *param; - // animate only top level params - for (param = getFirstVisualParam(); - param; - param = getNextVisualParam()) + if (!isSelf()) { - if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) + // animate only top level params for non-self avatars + for (param = getFirstVisualParam(); + param; + param = getNextVisualParam()) { - param->animate(morph_amt, mAppearanceAnimSetByUser); + if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) + { + param->animate(morph_amt, mAppearanceAnimSetByUser); + } } } @@ -2487,6 +2479,25 @@ void LLVOAvatar::idleUpdateAppearanceAnimation() } } +F32 LLVOAvatar::calcMorphAmount() +{ + F32 appearance_anim_time = mAppearanceMorphTimer.getElapsedTimeF32(); + F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME); + F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME); + + F32 morph_amt; + if (last_blend_frac == 1.f) + { + morph_amt = 1.f; + } + else + { + morph_amt = (blend_frac - last_blend_frac) / (1.f - last_blend_frac); + } + + return morph_amt; +} + void LLVOAvatar::idleUpdateLipSync(bool voice_enabled) { // Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index e3add8aa78..f7c794defe 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -205,7 +205,7 @@ public: virtual BOOL updateCharacter(LLAgent &agent); void idleUpdateVoiceVisualizer(bool voice_enabled); void idleUpdateMisc(bool detailed_update); - void idleUpdateAppearanceAnimation(); + virtual void idleUpdateAppearanceAnimation(); void idleUpdateLipSync(bool voice_enabled); void idleUpdateLoadingEffect(); void idleUpdateWindEffect(); @@ -250,6 +250,7 @@ protected: virtual BOOL updateIsFullyLoaded(); BOOL processFullyLoadedChange(bool loading); void updateRuthTimer(bool loading); + F32 calcMorphAmount(); private: BOOL mFullyLoaded; BOOL mPreviousFullyLoaded; @@ -276,7 +277,7 @@ public: protected: static BOOL parseSkeletonFile(const std::string& filename); void buildCharacter(); - BOOL loadAvatar(); + virtual BOOL loadAvatar(); BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info); diff --git a/indra/newview/llvoavatardefines.cpp b/indra/newview/llvoavatardefines.cpp index 17b502ae80..5624f19c8d 100644 --- a/indra/newview/llvoavatardefines.cpp +++ b/indra/newview/llvoavatardefines.cpp @@ -68,9 +68,9 @@ LLVOAvatarDictionary::Textures::Textures() addEntry(TEX_EYES_ALPHA, new TextureEntry("eyes_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA)); addEntry(TEX_HAIR_ALPHA, new TextureEntry("hair_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA)); - addEntry(TEX_HEAD_TATTOO, new TextureEntry("head_tattoo", TRUE, BAKED_NUM_INDICES, "UIImgDefaultTattooUUID", WT_TATTOO)); - addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "UIImgDefaultTattooUUID", WT_TATTOO)); - addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "UIImgDefaultTattooUUID", WT_TATTOO)); + addEntry(TEX_HEAD_TATTOO, new TextureEntry("head_tattoo", TRUE, BAKED_NUM_INDICES, "", WT_TATTOO)); + addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", WT_TATTOO)); + addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", WT_TATTOO)); addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD)); addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER)); @@ -248,8 +248,6 @@ EBakedTextureIndex LLVOAvatarDictionary::findBakedByRegionName(std::string name) //static const LLUUID LLVOAvatarDictionary::getDefaultTextureImageID(ETextureIndex index) { - /* switch( index ) - case TEX_UPPER_SHIRT: return LLUUID( gSavedSettings.getString("UIImgDefaultShirtUUID") ); */ const TextureEntry *texture_dict = getInstance()->getTexture(index); const std::string &default_image_name = texture_dict->mDefaultImageName; if (default_image_name == "") @@ -265,9 +263,6 @@ const LLUUID LLVOAvatarDictionary::getDefaultTextureImageID(ETextureIndex index) // static EWearableType LLVOAvatarDictionary::getTEWearableType(ETextureIndex index ) { - /* switch(index) - case TEX_UPPER_SHIRT: - return WT_SHIRT; */ return getInstance()->getTexture(index)->mWearableType; } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 4760d5a472..758db538a2 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -193,6 +193,25 @@ void LLVOAvatarSelf::markDead() LLVOAvatar::markDead(); } +/*virtual*/ BOOL LLVOAvatarSelf::loadAvatar() +{ + BOOL success = LLVOAvatar::loadAvatar(); + + // set all parameters sotred directly in the avatar to have + // the isSelfParam to be TRUE - this is used to prevent + // them from being animated or trigger accidental rebakes + // when we copy params from the wearable to the base avatar. + for (LLViewerVisualParam* param = (LLViewerVisualParam*) getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) getNextVisualParam()) + { + param->setIsDummy(TRUE); + } + + return success; +} + + BOOL LLVOAvatarSelf::loadAvatarSelf() { BOOL success = TRUE; @@ -704,16 +723,23 @@ void LLVOAvatarSelf::updateVisualParams() } } - LLWearable *shape = gAgentWearables.getWearable(WT_SHAPE,0); - if (shape) - { - F32 gender = shape->getVisualParamWeight(80); // param 80 == gender - setVisualParamWeight("male",gender ,TRUE); - } - LLVOAvatar::updateVisualParams(); } +/*virtual*/ +void LLVOAvatarSelf::idleUpdateAppearanceAnimation() +{ + // Animate all top-level wearable visual parameters + gAgentWearables.animateAllWearableParams(calcMorphAmount(), mAppearanceAnimSetByUser); + + // apply wearable visual params to avatar + updateVisualParams(); + + //allow avatar to process updates + LLVOAvatar::idleUpdateAppearanceAnimation(); + +} + // virtual void LLVOAvatarSelf::requestStopMotion(LLMotion* motion) { diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index a555d04a63..6e52b33634 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -57,6 +57,7 @@ public: virtual void markDead(); virtual void initInstance(); // Called after construction to initialize the class. protected: + /*virtual*/ BOOL loadAvatar(); BOOL loadAvatarSelf(); BOOL buildSkeletonSelf(const LLVOAvatarSkeletonInfo *info); BOOL buildMenus(); @@ -89,6 +90,7 @@ public: /*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user = FALSE ); /*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user = FALSE ); /*virtual*/ void updateVisualParams(); + /*virtual*/ void idleUpdateAppearanceAnimation(); private: // helper function. Passed in param is assumed to be in avatar's parameter list. diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 2834284a9b..df5481c874 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -254,6 +254,7 @@ protected: std::string nameString; std::string audioMediaString; std::string displayNameString; + std::string deviceString; int participantType; bool isLocallyMuted; bool isModeratorMuted; @@ -485,6 +486,14 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr) { gVoiceClient->clearRenderDevices(); } + else if (!stricmp("CaptureDevice", tag)) + { + deviceString.clear(); + } + else if (!stricmp("RenderDevice", tag)) + { + deviceString.clear(); + } else if (!stricmp("Buddies", tag)) { gVoiceClient->deleteAllBuddies(); @@ -508,7 +517,6 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr) void LLVivoxProtocolParser::EndTag(const char *tag) { const std::string& string = textBuffer; - bool clearbuffer = true; responseDepth--; @@ -580,6 +588,8 @@ void LLVivoxProtocolParser::EndTag(const char *tag) nameString = string; else if (!stricmp("DisplayName", tag)) displayNameString = string; + else if (!stricmp("Device", tag)) + deviceString = string; else if (!stricmp("AccountName", tag)) nameString = string; else if (!stricmp("ParticipantType", tag)) @@ -596,18 +606,13 @@ void LLVivoxProtocolParser::EndTag(const char *tag) uriString = string; else if (!stricmp("Presence", tag)) statusString = string; - else if (!stricmp("Device", tag)) - { - // This closing tag shouldn't clear the accumulated text. - clearbuffer = false; - } else if (!stricmp("CaptureDevice", tag)) { - gVoiceClient->addCaptureDevice(textBuffer); + gVoiceClient->addCaptureDevice(deviceString); } else if (!stricmp("RenderDevice", tag)) { - gVoiceClient->addRenderDevice(textBuffer); + gVoiceClient->addRenderDevice(deviceString); } else if (!stricmp("Buddy", tag)) { @@ -648,12 +653,8 @@ void LLVivoxProtocolParser::EndTag(const char *tag) else if (!stricmp("SubscriptionType", tag)) subscriptionType = string; - - if(clearbuffer) - { - textBuffer.clear(); - accumulateText= false; - } + textBuffer.clear(); + accumulateText= false; if (responseDepth == 0) { @@ -1160,7 +1161,8 @@ LLVoiceClient::LLVoiceClient() : mVoiceEnabled(false), mWriteInProgress(false), - mLipSyncEnabled(false) + mLipSyncEnabled(false), + mAPIVersion("Unknown") { gVoiceClient = this; @@ -3749,6 +3751,7 @@ void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusS { // Connector created, move forward. LL_INFOS("Voice") << "Connector.Create succeeded, Vivox SDK version is " << versionID << LL_ENDL; + mAPIVersion = versionID; mConnectorHandle = connectorHandle; if(getState() == stateConnectorStarting) { diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index bddd18dee8..9df96d9a52 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -204,6 +204,9 @@ static void updatePosition(void); void keyDown(KEY key, MASK mask); void keyUp(KEY key, MASK mask); void middleMouseState(bool down); + + // Return the version of the Vivox library + std::string getAPIVersion() const { return mAPIVersion; } ///////////////////////////// // Accessors for data related to nearby speakers @@ -739,6 +742,8 @@ static std::string nameFromsipURI(const std::string &uri); BOOL mLipSyncEnabled; + std::string mAPIVersion; + typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t; observer_set_t mParticipantObservers; diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 7585842623..143cd2d9c6 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -249,6 +249,12 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) facep->mCenterLocal = part->mPosAgent; facep->setFaceColor(part->mColor); facep->setTexture(part->mImagep); + + //check if this particle texture is replaced by a parcel media texture. + if(part->mImagep.notNull() && part->mImagep->hasParcelMedia()) + { + part->mImagep->getParcelMedia()->addMediaToFace(facep) ; + } mPixelArea = tot_area * pixel_meter_ratio; const F32 area_scale = 10.f; // scale area to increase priority a bit diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index a091028ec2..4cd29bb838 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -185,7 +185,9 @@ void LLWearable::createVisualParams() { delete mVisualParamIndexMap[param->getID()]; } - mVisualParamIndexMap[param->getID()] = param->cloneParam(this); + LLViewerVisualParam *new_param = param->cloneParam(this); + new_param->setIsDummy(FALSE); + mVisualParamIndexMap[param->getID()] = new_param; } } @@ -668,21 +670,7 @@ void LLWearable::writeToAvatar( BOOL set_by_user, BOOL update_customize_floater if( gFloaterCustomize && update_customize_floater ) { - LLViewerInventoryItem* item; - // MULTI_WEARABLE: - item = (LLViewerInventoryItem*)gInventory.getItem(gAgentWearables.getWearableItemID(mType,0)); - U32 perm_mask = PERM_NONE; - BOOL is_complete = FALSE; - if(item) - { - perm_mask = item->getPermissions().getMaskOwner(); - is_complete = item->isComplete(); - if(!is_complete) - { - item->fetchFromServer(); - } - } - gFloaterCustomize->setWearable(mType, this, perm_mask, is_complete); + gFloaterCustomize->setWearable(mType, 0); gFloaterCustomize->setCurrentWearableType( mType ); } @@ -935,6 +923,17 @@ void LLWearable::getVisualParams(visual_param_vec_t &list) } } +void LLWearable::animateParams(F32 delta, BOOL set_by_user) +{ + for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); + iter != mVisualParamIndexMap.end(); + ++iter) + { + LLVisualParam *param = (LLVisualParam*) iter->second; + param->animate(delta, set_by_user); + } +} + LLColor4 LLWearable::getClothesColor(S32 te) const { LLColor4 color; diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h index 01bd9652a5..96631811c5 100644 --- a/indra/newview/llwearable.h +++ b/indra/newview/llwearable.h @@ -119,6 +119,7 @@ public: F32 getVisualParamWeight(S32 index) const; LLVisualParam* getVisualParam(S32 index) const; void getVisualParams(visual_param_vec_t &list); + void animateParams(F32 delta, BOOL set_by_user); LLColor4 getClothesColor(S32 te) const; void setClothesColor( S32 te, const LLColor4& new_color, BOOL set_by_user ); diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 829d631473..f198f3a0cf 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -37,7 +37,6 @@ #include "llregionhandle.h" #include "message.h" -#include "llappviewer.h" // for gPacificDaylightTime #include "llagent.h" #include "llmapresponders.h" #include "llviewercontrol.h" diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 287c997c65..1e0da13162 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -66,6 +66,9 @@ name="Blue" value="0 0 1 1" /> <color + name="Yellow" + value="1 1 0 1" /> + <color name="Unused?" value="1 0 1 1" /> <color @@ -408,10 +411,10 @@ reference="White" /> <color name="MapAvatarColor" - reference="White" /> + reference="Green" /> <color name="MapAvatarFriendColor" - reference="Unused?" /> + reference="Yellow" /> <color name="MapAvatarSelfColor" value="0.53125 0 0.498047 1" /> diff --git a/indra/newview/skins/default/textures/containers/Accordion_Selected.png b/indra/newview/skins/default/textures/containers/Accordion_Selected.png Binary files differnew file mode 100644 index 0000000000..0616dea6a3 --- /dev/null +++ b/indra/newview/skins/default/textures/containers/Accordion_Selected.png diff --git a/indra/newview/skins/default/textures/icons/ForSale_Badge.png b/indra/newview/skins/default/textures/icons/ForSale_Badge.png Binary files differnew file mode 100644 index 0000000000..5bee570cee --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ForSale_Badge.png diff --git a/indra/newview/skins/default/textures/icons/Generic_Object_Small.png b/indra/newview/skins/default/textures/icons/Generic_Object_Small.png Binary files differnew file mode 100644 index 0000000000..223874e631 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Generic_Object_Small.png diff --git a/indra/newview/skins/default/textures/icons/Inv_LookFolderClosed.png b/indra/newview/skins/default/textures/icons/Inv_LookFolderClosed.png Binary files differnew file mode 100644 index 0000000000..f2ae828efc --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Inv_LookFolderClosed.png diff --git a/indra/newview/skins/default/textures/icons/Inv_LookFolderOpen.png b/indra/newview/skins/default/textures/icons/Inv_LookFolderOpen.png Binary files differnew file mode 100644 index 0000000000..d454d4cd48 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Inv_LookFolderOpen.png diff --git a/indra/newview/skins/default/textures/icons/YouAreHere_Badge.png b/indra/newview/skins/default/textures/icons/YouAreHere_Badge.png Binary files differnew file mode 100644 index 0000000000..c057e9743d --- /dev/null +++ b/indra/newview/skins/default/textures/icons/YouAreHere_Badge.png diff --git a/indra/newview/skins/default/textures/map_avatar_8.tga b/indra/newview/skins/default/textures/map_avatar_8.tga Binary files differindex 47c8cbed6f..28552f2237 100644 --- a/indra/newview/skins/default/textures/map_avatar_8.tga +++ b/indra/newview/skins/default/textures/map_avatar_8.tga diff --git a/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png Binary files differindex 7c10aaaead..41cb88628a 100644 --- a/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png +++ b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png diff --git a/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png Binary files differindex 9d7716c6de..a02675502a 100644 --- a/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png +++ b/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 7f9d09a7d6..4d9cac3672 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -6,6 +6,8 @@ <texture name="Accordion_ArrowOpened_Press" file_name="containers/Accordion_ArrowOpened_Press.png" preload="false" /> <texture name="Accordion_Off" file_name="containers/Accordion_Off.png" preload="false" /> <texture name="Accordion_Press" file_name="containers/Accordion_Press.png" preload="false" /> + <texture name="Accordion_Over" file_name="containers/Accordion_Over.png" preload="false" /> + <texture name="Accordion_Selected" file_name="containers/Accordion_Selected.png" preload="false" /> <texture name="Activate_Checkmark" file_name="taskpanel/Activate_Checkmark.png" preload="false" /> @@ -27,9 +29,9 @@ <texture name="BottomTray_BG" file_name="bottomtray/BottomTray_BG.png" preload="false" /> - <texture name="BuyArrow_Off" file_name="navbar/BuyArrow_Off.png" preload="false" /> - <texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="false" /> - <texture name="BuyArrow_Press" file_name="navbar/BuyArrow_Press.png" preload="false" /> + <texture name="BuyArrow_Off" file_name="navbar/BuyArrow_Off.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" /> + <texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" /> + <texture name="BuyArrow_Press" file_name="navbar/BuyArrow_Press.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" /> <texture name="Cam_Avatar_Disabled" file_name="bottomtray/Cam_Avatar_Disabled.png" preload="false" /> <texture name="Cam_Avatar_Over" file_name="bottomtray/Cam_Avatar_Over.png" preload="false" /> @@ -54,11 +56,6 @@ <texture name="CameraView_Off" file_name="bottomtray/CameraView_Off.png" preload="false" /> <texture name="CameraView_Over" file_name="bottomtray/CameraView_Over.png" preload="false" /> - <texture name="CameraPreset_Rear" file_name="camera_presets/camera_presets_rear.png" preload="false" /> - <texture name="CameraPreset_3_4" file_name="camera_presets/camera_presets_3_4.png" preload="false" /> - <texture name="CameraPreset_Front" file_name="camera_presets/camera_presets_front.png" preload="false" /> - <texture name="CameraPreset_Mouselook" file_name="camera_presets/camera_presets_mouselook.png" preload="false" /> - <texture name="Checkbox_Off_Disabled" file_name="widgets/Checkbox_Disabled.png" preload="true" /> <texture name="Checkbox_On_Disabled" file_name="widgets/Checkbox_On_Disabled.png" preload="true" /> <texture name="Checkbox_Off" file_name="widgets/Checkbox_Off.png" preload="true" /> @@ -93,15 +90,18 @@ <texture name="Favorite_Star_Press" file_name="navbar/Favorite_Star_Press.png" preload="false" /> <texture name="Favorite_Star_Over" file_name="navbar/Favorite_Star_Over.png" preload="false" /> - <texture name="FileMenu_BarSelect" file_name="navbar/FileMenu_BarSelect.png" preload="false" /> + <texture name="FileMenu_BarSelect" file_name="navbar/FileMenu_BarSelect.png" preload="false" scale.left="2" scale.top="0" scale.right="2" scale.bottom="0" /> <texture name="FileMenu_BG" file_name="navbar/FileMenu_BG.png" preload="false" /> + <texture name="ForSale_Badge" file_name="icons/ForSale_Badge.png" preload="false" /> <texture name="ForwardArrow_Off" file_name="icons/ForwardArrow_Off.png" preload="false" /> <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="Generic_Group_Large" file_name="icons/Generic_Group_Large.png" preload="false" /> - <texture name="Generic_Object" file_name="icons/Generic_Object.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" /> + <texture name="Generic_Object_Large" file_name="icons/Generic_Object_Large.png" preload="false" /> <texture name="Generic_Person" file_name="icons/Generic_Person.png" preload="false" /> <texture name="Generic_Person_Large" file_name="icons/Generic_Person_Large.png" preload="false" /> @@ -147,10 +147,12 @@ <texture name="Info_Over" file_name="icons/Info_Over.png" preload="false" /> <texture name="Info_Press" file_name="navbar/Info_Press.png" preload="false" /> - <texture name="Inspector_Background" file_name="windows/Inspector_Background.png" preload="false" /> + <texture name="Inspector_Background" file_name="windows/Inspector_Background.png" preload="false" + scale.left="4" scale.top="28" scale.right="60" scale.bottom="4" /> <texture name="Inspector_Hover" file_name="windows/Inspector_Hover.png" preload="false" /> <texture name="Inv_Acessories" file_name="icons/Inv_Accessories.png" preload="false" /> + <texture name="Inv_Alpha" file_name="icons/Inv_Alpha.png" preload="false" /> <texture name="Inv_Animation" file_name="icons/Inv_Animation.png" preload="false" /> <texture name="Inv_BodyShape" file_name="icons/Inv_BodyShape.png" preload="false" /> <texture name="Inv_CallingCard" file_name="icons/Inv_CallingCard.png" preload="false" /> @@ -163,6 +165,8 @@ <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_Jacket" file_name="icons/Inv_Jacket.png" preload="false" /> + <texture name="Inv_LookFolderOpen" file_name="icons/Inv_LookFolderOpen.png" preload="false" /> + <texture name="Inv_LookFolderClosed" file_name="icons/Inv_LookFolderClosed.png" preload="false" /> <texture name="Inv_Landmark" file_name="icons/Inv_Landmark.png" preload="false" /> <texture name="Inv_Notecard" file_name="icons/Inv_Notecard.png" preload="false" /> <texture name="Inv_Object" file_name="icons/Inv_Object.png" preload="false" /> @@ -175,6 +179,7 @@ <texture name="Inv_Snapshot" file_name="icons/Inv_Snapshot.png" preload="false" /> <texture name="Inv_Socks" file_name="icons/Inv_Socks.png" preload="false" /> <texture name="Inv_Sound" file_name="icons/Inv_Sound.png" preload="false" /> + <texture name="Inv_Tattoo" file_name="icons/Inv_Tattoo.png" preload="false" /> <texture name="Inv_Texture" file_name="icons/Inv_Texture.png" preload="false" /> <texture name="Inv_Trash" file_name="icons/Inv_Trash.png" preload="false" /> <texture name="Inv_Underpants" file_name="icons/Inv_Underpants.png" preload="false" /> @@ -228,9 +233,6 @@ <texture name="NearbyVoice_Lvl3" file_name="bottomtray/NearbyVoice_Lvl3.png" preload="false" /> <texture name="NearbyVoice_On" file_name="bottomtray/NearbyVoice_On.png" preload="false" /> - <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" /> @@ -259,40 +261,40 @@ <texture name="Overhead_S" file_name="world/Overhead_S.png" preload="false" /> <texture name="parcel_drk_Build" file_name="icons/parcel_drk_Build.png" preload="false" /> - <texture name="parcel_drk_BuildNo" file_name="icons/parcel_drk_BuildNo.png" preload="false" /> - <texture name="parcel_drk_Damage" file_name="icons/parcel_drk_Damage.png" preload="false" /> - <texture name="parcel_drk_DamageNo" file_name="icons/parcel_drk_DamageNo.png" preload="false" /> - <texture name="parcel_drk_Fly" file_name="icons/parcel_drk_Fly.png" preload="false" /> - <texture name="parcel_drk_FlyNo" file_name="icons/parcel_drk_FlyNo.png" preload="false" /> - <texture name="parcel_drk_ForSale" file_name="icons/parcel_drk_ForSale.png" preload="false" /> - <texture name="parcel_drk_ForSaleNo" file_name="icons/parcel_drk_ForSaleNo.png" preload="false" /> - <texture name="parcel_drk_M" file_name="icons/parcel_drk_M.png" preload="false" /> - <texture name="parcel_drk_PG" file_name="icons/parcel_drk_PG.png" preload="false" /> - <texture name="parcel_drk_Push" file_name="icons/parcel_drk_Push.png" preload="false" /> - <texture name="parcel_drk_PushNo" file_name="icons/parcel_drk_PushNo.png" preload="false" /> - <texture name="parcel_drk_R" file_name="icons/parcel_drk_R.png" preload="false" /> - <texture name="parcel_drk_Scripts" file_name="icons/parcel_drk_Scripts.png" preload="false" /> - <texture name="parcel_drk_ScriptsNo" file_name="icons/parcel_drk_ScriptsNo.png" preload="false" /> - <texture name="parcel_drk_Voice" file_name="icons/parcel_drk_Voice.png" preload="false" /> - <texture name="parcel_drk_VoiceNo" file_name="icons/parcel_drk_VoiceNo.png" preload="false" /> - - <texture name="parcel_lght_Build" file_name="icons/parcel_lght_Build.png" preload="false" /> - <texture name="parcel_lght_BuildNo" file_name="icons/parcel_lght_BuildNo.png" preload="false" /> - <texture name="parcel_lght_Damage" file_name="icons/parcel_lght_Damage.png" preload="false" /> - <texture name="parcel_lght_DamageNo" file_name="icons/parcel_lght_DamageNo.png" preload="false" /> - <texture name="parcel_lght_Fly" file_name="icons/parcel_lght_Fly.png" preload="false" /> - <texture name="parcel_lght_FlyNo" file_name="icons/parcel_lght_FlyNo.png" preload="false" /> - <texture name="parcel_lght_ForSale" file_name="icons/parcel_lght_ForSale.png" preload="false" /> - <texture name="parcel_lght_ForSaleNo" file_name="icons/parcel_lght_ForSaleNo.png" preload="false" /> - <texture name="parcel_lght_M" file_name="icons/parcel_lght_M.png" preload="false" /> - <texture name="parcel_lght_PG" file_name="icons/parcel_lght_PG.png" preload="false" /> - <texture name="parcel_lght_Push" file_name="icons/parcel_lght_Push.png" preload="false" /> - <texture name="parcel_lght_PushNo" file_name="icons/parcel_lght_PushNo.png" preload="false" /> - <texture name="parcel_lght_R" file_name="icons/parcel_lght_R.png" preload="false" /> - <texture name="parcel_lght_Scripts" file_name="icons/parcel_lght_Scripts.png" preload="false" /> - <texture name="parcel_lght_ScriptsNo" file_name="icons/parcel_lght_ScriptsNo.png" preload="false" /> - <texture name="parcel_lght_Voice" file_name="icons/parcel_lght_Voice.png" preload="false" /> - <texture name="parcel_lght_VoiceNo" file_name="icons/parcel_lght_VoiceNo.png" preload="false" /> + <texture name="parcel_drk_BuildNo" file_name="icons/parcel_drk_BuildNo.png" preload="false" /> + <texture name="parcel_drk_Damage" file_name="icons/parcel_drk_Damage.png" preload="false" /> + <texture name="parcel_drk_DamageNo" file_name="icons/parcel_drk_DamageNo.png" preload="false" /> + <texture name="parcel_drk_Fly" file_name="icons/parcel_drk_Fly.png" preload="false" /> + <texture name="parcel_drk_FlyNo" file_name="icons/parcel_drk_FlyNo.png" preload="false" /> + <texture name="parcel_drk_ForSale" file_name="icons/parcel_drk_ForSale.png" preload="false" /> + <texture name="parcel_drk_ForSaleNo" file_name="icons/parcel_drk_ForSaleNo.png" preload="false" /> + <texture name="parcel_drk_M" file_name="icons/parcel_drk_M.png" preload="false" /> + <texture name="parcel_drk_PG" file_name="icons/parcel_drk_PG.png" preload="false" /> + <texture name="parcel_drk_Push" file_name="icons/parcel_drk_Push.png" preload="false" /> + <texture name="parcel_drk_PushNo" file_name="icons/parcel_drk_PushNo.png" preload="false" /> + <texture name="parcel_drk_R" file_name="icons/parcel_drk_R.png" preload="false" /> + <texture name="parcel_drk_Scripts" file_name="icons/parcel_drk_Scripts.png" preload="false" /> + <texture name="parcel_drk_ScriptsNo" file_name="icons/parcel_drk_ScriptsNo.png" preload="false" /> + <texture name="parcel_drk_Voice" file_name="icons/parcel_drk_Voice.png" preload="false" /> + <texture name="parcel_drk_VoiceNo" file_name="icons/parcel_drk_VoiceNo.png" preload="false" /> + + <texture name="parcel_lght_Build" file_name="icons/parcel_lght_Build.png" preload="false" /> + <texture name="parcel_lght_BuildNo" file_name="icons/parcel_lght_BuildNo.png" preload="false" /> + <texture name="parcel_lght_Damage" file_name="icons/parcel_lght_Damage.png" preload="false" /> + <texture name="parcel_lght_DamageNo" file_name="icons/parcel_lght_DamageNo.png" preload="false" /> + <texture name="parcel_lght_Fly" file_name="icons/parcel_lght_Fly.png" preload="false" /> + <texture name="parcel_lght_FlyNo" file_name="icons/parcel_lght_FlyNo.png" preload="false" /> + <texture name="parcel_lght_ForSale" file_name="icons/parcel_lght_ForSale.png" preload="false" /> + <texture name="parcel_lght_ForSaleNo" file_name="icons/parcel_lght_ForSaleNo.png" preload="false" /> + <texture name="parcel_lght_M" file_name="icons/parcel_lght_M.png" preload="false" /> + <texture name="parcel_lght_PG" file_name="icons/parcel_lght_PG.png" preload="false" /> + <texture name="parcel_lght_Push" file_name="icons/parcel_lght_Push.png" preload="false" /> + <texture name="parcel_lght_PushNo" file_name="icons/parcel_lght_PushNo.png" preload="false" /> + <texture name="parcel_lght_R" file_name="icons/parcel_lght_R.png" preload="false" /> + <texture name="parcel_lght_Scripts" file_name="icons/parcel_lght_Scripts.png" preload="false" /> + <texture name="parcel_lght_ScriptsNo" file_name="icons/parcel_lght_ScriptsNo.png" preload="false" /> + <texture name="parcel_lght_Voice" file_name="icons/parcel_lght_Voice.png" preload="false" /> + <texture name="parcel_lght_VoiceNo" file_name="icons/parcel_lght_VoiceNo.png" preload="false" /> <texture name="Progress_1" file_name="icons/Progress_1.png" preload="false" /> <texture name="Progress_2" file_name="icons/Progress_2.png" preload="false" /> @@ -441,7 +443,8 @@ <texture name="TextField_Active" file_name="widgets/TextField_Active.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" /> <texture name="Toast_CloseBtn" file_name="windows/Toast_CloseBtn.png" preload="true" /> - <texture name="Toast" file_name="windows/Toast.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="Tool_Create" file_name="build/Tool_Create.png" preload="false" /> <texture name="Tool_Dozer" file_name="build/Tool_Dozer.png" preload="false" /> @@ -476,18 +479,19 @@ <texture name="Widget_DownArrow" file_name="icons/Widget_DownArrow.png" preload="true" /> <texture name="Widget_UpArrow" file_name="icons/Widget_UpArrow.png" preload="true" /> - <texture name="Window_Background" file_name="windows/Window_Background.png" preload="true" /> - <texture name="Window_Foreground" file_name="windows/Window_Foreground.png" preload="true" /> - - - + <texture name="Window_Background" file_name="windows/Window_Background.png" preload="true" + scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" /> + <texture name="Window_Foreground" file_name="windows/Window_Foreground.png" preload="true" + scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" /> + <texture name="Window_NoTitle_Background" file_name="windows/Window_NoTitle_Background.png" preload="true" + scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" /> + <texture name="Window_NoTitle_Foreground" file_name="windows/Window_NoTitle_Foreground.png" preload="true" + scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" /> + <texture name="YouAreHere_Badge" file_name="icons/YouAreHere_Badge.png" preload="false" /> <!--WARNING OLD ART *do not use*--> - <texture name="Banner_ForSale" file_name="Banner_ForSale.png" preload="false" /> - <texture name="Banner_YouAreHere" file_name="Banner_YouAreHere.png" preload="false" /> - <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" /> @@ -605,6 +609,54 @@ <texture name="icon_popular.tga" /> <texture name="icon_top_pick.tga" /> + <texture name="inv_folder_animation.tga" /> + <texture name="inv_folder_bodypart.tga" /> + <texture name="inv_folder_callingcard.tga" /> + <texture name="inv_folder_clothing.tga" /> + <texture name="inv_folder_current_outfit.tga" /> + <texture name="inv_folder_gesture.tga" /> + <texture name="inv_folder_landmark.tga" /> + <texture name="inv_folder_lostandfound.tga" /> + <texture name="inv_folder_my_outfits.tga" /> + <texture name="inv_folder_notecard.tga" /> + <texture name="inv_folder_object.tga" /> + <texture name="inv_folder_outfit.tga" /> + <texture name="inv_folder_plain_closed.tga" /> + <texture name="inv_folder_script.tga" /> + <texture name="inv_folder_snapshot.tga" /> + <texture name="inv_folder_sound.tga" /> + <texture name="inv_folder_texture.tga" /> + <texture name="inv_folder_trash.tga" /> + + <texture name="inv_item_animation.tga" /> + <texture name="inv_item_skin.tga" /> + <texture name="inv_item_callingcard_offline.tga" /> + <texture name="inv_item_callingcard_online.tga" /> + <texture name="inv_item_eyes.tga" /> + <texture name="inv_item_gesture.tga" /> + <texture name="inv_item_gloves.tga" /> + <texture name="inv_item_hair.tga" /> + <texture name="inv_item_jacket.tga" /> + <texture name="inv_item_landmark.tga" /> + <texture name="inv_item_landmark_visited.tga" /> + <texture name="inv_item_linkitem.tga" /> + <texture name="inv_item_linkfolder.tga" /> + <texture name="inv_item_notecard.tga" /> + <texture name="inv_item_object.tga" /> + <texture name="inv_item_object_multi.tga" /> + <texture name="inv_item_pants.tga" /> + <texture name="inv_item_script.tga" /> + <texture name="inv_item_shape.tga" /> + <texture name="inv_item_shirt.tga" /> + <texture name="inv_item_shoes.tga" /> + <texture name="inv_item_skirt.tga" /> + <texture name="inv_item_snapshot.tga" /> + <texture name="inv_item_socks.tga" /> + <texture name="inv_item_sound.tga" /> + <texture name="inv_item_texture.tga" /> + <texture name="inv_item_underpants.tga" /> + <texture name="inv_item_undershirt.tga" /> + <texture name="lag_status_critical.tga" /> <texture name="lag_status_good.tga" /> <texture name="lag_status_warning.tga" /> @@ -623,12 +675,45 @@ <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" /> <texture name="notify_next.png" preload="true" /> <texture name="notify_box_icon.tga" /> + <texture name="object_cone.tga" /> + <texture name="object_cone_active.tga" /> + <texture name="object_cube.tga" /> + <texture name="object_cube_active.tga" /> + <texture name="object_cylinder.tga" /> + <texture name="object_cylinder_active.tga" /> + <texture name="object_grass.tga" /> + <texture name="object_grass_active.tga" /> + <texture name="object_hemi_cone.tga" /> + <texture name="object_hemi_cone_active.tga" /> + <texture name="object_hemi_cylinder.tga" /> + <texture name="object_hemi_cylinder_active.tga" /> + <texture name="object_hemi_sphere.tga" /> + <texture name="object_hemi_sphere_active.tga" /> + <texture name="object_prism.tga" /> + <texture name="object_prism_active.tga" /> + <texture name="object_pyramid.tga" /> + <texture name="object_pyramid_active.tga" /> + <texture name="object_ring.tga" /> + <texture name="object_ring_active.tga" /> + <texture name="object_sphere.tga" /> + <texture name="object_sphere_active.tga" /> + <texture name="object_tetrahedron.tga" /> + <texture name="object_tetrahedron_active.tga" /> + <texture name="object_torus.tga" /> + <texture name="object_torus_active.tga" /> + <texture name="object_tree.tga" /> + <texture name="object_tree_active.tga" /> + <texture name="object_tube.tga" /> + <texture name="object_tube_active.tga" /> + <texture name="pixiesmall.j2c" use_mips="true" /> <texture name="script_error.j2c" use_mips="true" /> <texture name="silhouette.j2c" use_mips="true" /> @@ -644,6 +729,11 @@ <texture name="status_no_push.tga" /> <texture name="status_no_scripts.tga" /> + <texture name="tool_dozer.tga" /> + <texture name="tool_dozer_active.tga" /> + <texture name="tool_zoom.tga" /> + <texture name="tool_zoom_active.tga" /> + <texture name="icn_active-speakers-dot-lvl0.tga" /> <texture name="icn_active-speakers-dot-lvl1.tga" /> <texture name="icn_active-speakers-dot-lvl2.tga" /> diff --git a/indra/newview/skins/default/textures/windows/Inspector_Background.png b/indra/newview/skins/default/textures/windows/Inspector_Background.png Binary files differindex 807e8e553c..4c2a728ac5 100644 --- a/indra/newview/skins/default/textures/windows/Inspector_Background.png +++ b/indra/newview/skins/default/textures/windows/Inspector_Background.png diff --git a/indra/newview/skins/default/textures/windows/Toast_Background.png b/indra/newview/skins/default/textures/windows/Toast_Background.png Binary files differnew file mode 100644 index 0000000000..f27d1a12ec --- /dev/null +++ b/indra/newview/skins/default/textures/windows/Toast_Background.png diff --git a/indra/newview/skins/default/textures/windows/Window_Background.png b/indra/newview/skins/default/textures/windows/Window_Background.png Binary files differindex e9f15e76b9..db253900af 100644 --- a/indra/newview/skins/default/textures/windows/Window_Background.png +++ b/indra/newview/skins/default/textures/windows/Window_Background.png diff --git a/indra/newview/skins/default/textures/windows/Window_Foreground.png b/indra/newview/skins/default/textures/windows/Window_Foreground.png Binary files differindex e76e9f3c79..b81ec5b43c 100644 --- a/indra/newview/skins/default/textures/windows/Window_Foreground.png +++ b/indra/newview/skins/default/textures/windows/Window_Foreground.png diff --git a/indra/newview/skins/default/textures/windows/Window_NoTitle_Background.png b/indra/newview/skins/default/textures/windows/Window_NoTitle_Background.png Binary files differnew file mode 100644 index 0000000000..a570ac06bd --- /dev/null +++ b/indra/newview/skins/default/textures/windows/Window_NoTitle_Background.png diff --git a/indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.png b/indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.png Binary files differnew file mode 100644 index 0000000000..d573e8c69a --- /dev/null +++ b/indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.png diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml index 6d64d13db7..3789369e74 100644 --- a/indra/newview/skins/default/xui/en/floater_aaa.xml +++ b/indra/newview/skins/default/xui/en/floater_aaa.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="440" layout="topleft" name="floater_aaa" diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 5cd11ba292..3f2636ae52 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="440" layout="topleft" name="floater_about" @@ -48,6 +49,7 @@ libcurl Version: [LIBCURL_VERSION] J2C Decoder Version: [J2C_VERSION] Audio Driver Version: [AUDIO_DRIVER_VERSION] Qt Webkit Version: [QT_WEBKIT_VERSION] +Vivox Version: [VIVOX_VERSION] </floater.string> <floater.string name="none"> 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 aa0b4094b4..e13aa610e5 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_tear_off="false" height="420" layout="topleft" @@ -25,26 +26,28 @@ remaining </floater.string> <tab_container - follows="left|top|right|bottom" + follows="all" height="400" + halign="center" layout="topleft" font="SansSerifSmall" left="1" - tab_padding_right="5" + tab_padding_right="5" + tab_height="20" name="landtab" tab_position="top" top="20" width="459"> - <panel + <panel border="true" - follows="left|top|right|bottom" + follows="all" height="380" label="General" layout="topleft" left="1" help_topic="land_general_tab" name="land_general_panel" - top="-31" + top="0" width="458"> <panel.string name="new users only"> @@ -533,7 +536,7 @@ Go to World menu > About Land or select another parcel to show its details. </panel> <panel border="true" - follows="left|top|right|bottom" + follows="all" height="380" label="Covenant" layout="topleft" @@ -629,7 +632,7 @@ Go to World menu > About Land or select another parcel to show its details. length="1" enabled="false" follows="left|top|right|bottom" - handle_edit_keys_directly="true" + handle_edit_keys_directly="true" height="115" layout="topleft" left_delta="0" @@ -800,7 +803,7 @@ Go to World menu > About Land or select another parcel to show its details. </panel> <panel border="true" - follows="left|top|right|bottom" + follows="all" height="380" label="Objects" layout="topleft" @@ -1166,7 +1169,7 @@ Go to World menu > About Land or select another parcel to show its details. </panel> <panel border="true" - follows="left|top|right|bottom" + follows="all" height="333" label="Options" layout="topleft" @@ -1602,16 +1605,15 @@ Only large parcels can be listed in search. value="Anywhere" /> </combo_box> </panel> - <panel + <panel border="true" - follows="left|top|right|bottom" + follows="all" height="363" label="Media" layout="topleft" left_delta="0" help_topic="land_media_tab" name="land_media_panel" - top_delta="1" width="458"> <text type="string" @@ -1622,24 +1624,22 @@ Only large parcels can be listed in search. left="10" name="with media:" top="9" - width="65"> + width="100"> Type: </text> <combo_box - height="18" + height="20" layout="topleft" - left_pad="5" + left_pad="10" name="media type" tool_tip="Specify if the URL is a movie, web page, or other media" - top_delta="-2" - width="120" /> + width="150" /> <text follows="left|top" height="16" layout="topleft" left_pad="10" name="mime_type" - top_delta="2" width="200" /> <text type="string" @@ -1649,32 +1649,30 @@ Only large parcels can be listed in search. layout="topleft" left="10" name="at URL:" - top="29" - width="65"> + top_pad="10" + width="100"> Home URL: </text> <line_editor - bottom_delta="0" follows="left|top" - height="16" + height="20" layout="topleft" - left="80" + left_pad="10" max_length="255" name="media_url" - right="-80" select_on_focus="true" - text_readonly_color="0.576471 0.662745 0.835294 1" /> + width="270" + /> <button follows="left|top" font="SansSerifSmall" - height="16" - label="Set..." - label_selected="Set..." + height="20" + label="Set" + label_selected="Set" layout="topleft" - left_pad="8" + left_pad="5" name="set_media_url" - top_delta="0" - width="60" /> + width="50" /> <text type="string" length="1" @@ -1683,37 +1681,34 @@ Only large parcels can be listed in search. layout="topleft" left="10" name="CurrentURL:" - top="49" - width="65"> + top_pad="10" + width="100"> Current URL: </text> <text follows="left|top" height="16" layout="topleft" - left_pad="5" + left_pad="10" name="current_url" - top_delta="0" - width="300" /> + width="260">http://</text> <button follows="left|top" - font="SansSerifSmall" - height="16" - label="Reset..." - label_selected="Reset..." + height="20" + label="Reset" + label_selected="Reset" layout="topleft" left_pad="6" name="reset_media_url" - top_delta="0" width="60" /> <check_box height="16" label="Hide URL" layout="topleft" - left="100" + left="120" name="hide_media_url" tool_tip="Checking this option will hide the media url to any non-authorized viewers of this parcel information. Note this is not available for HTML types." - top="89" + top_pad="2" width="200" /> <text type="string" @@ -1723,23 +1718,20 @@ Only large parcels can be listed in search. layout="topleft" left="10" name="Description:" - top="49" - width="364"> + top_pad="10" + width="100"> Description: </text> <line_editor - border_style="line" - border_thickness="1" - bottom_delta="0" follows="left|top" - height="16" + height="35" layout="topleft" - left="80" - max_length="255" name="url_description" - right="-80" + left_pad="10" select_on_focus="true" - tool_tip="Text displayed next to play/load button" /> + tool_tip="Text displayed next to play/load button" + top_delta="0" + width="270" /> <text type="string" length="1" @@ -1748,10 +1740,9 @@ Only large parcels can be listed in search. layout="topleft" left="10" name="Media texture:" - top="69" - width="364"> - Replace -Texture: + top_pad="10" + width="100"> + Replace Texture: </text> <texture_picker allow_no_texture="true" @@ -1759,7 +1750,7 @@ Texture: follows="left|top" height="80" layout="topleft" - left_delta="70" + left_pad="10" name="media texture" tool_tip="Click to choose a picture" top_delta="0" @@ -1768,25 +1759,22 @@ Texture: type="string" length="1" follows="left|top" - height="16" + height="50" layout="topleft" - left_delta="75" + left_pad="10" name="replace_texture_help" - top="85" - width="270"> - Objects using this texture will show the movie or - web page after you click the play arrow. - - Select the thumbnail to choose a different texture. + top_delta="0" + word_wrap="true" + width="240"> + Objects using this texture will show the movie or web page after you click the play arrow. </text> <check_box height="16" label="Auto scale" layout="topleft" - left_delta="70" name="media_auto_scale" tool_tip="Checking this option will scale the content for this parcel automatically. It may be slightly slower and lower quality visually but no other texture scaling or alignment will be required." - top_delta="0" + top_pad="3" width="200" /> <text type="string" @@ -1794,11 +1782,11 @@ Texture: follows="left|top" height="16" layout="topleft" - left="85" + left="10" + top_pad="10" name="media_size" tool_tip="Size to render Web media, leave 0 for default." - top="185" - width="85"> + width="100"> Size: </text> <spinner @@ -1810,12 +1798,22 @@ Texture: increment="1" initial_value="0" layout="topleft" - left_delta="65" + left_pad="10" max_val="1024" name="media_size_width" tool_tip="Size to render Web media, leave 0 for default." top_delta="0" width="64" /> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left_pad="5" + name="pixels"> + px wide + </text> <spinner decimal_digits="0" enabled="false" @@ -1825,23 +1823,21 @@ Texture: increment="1" initial_value="0" layout="topleft" - left_pad="16" + left="120" + top_pad="3" max_val="1024" name="media_size_height" tool_tip="Size to render Web media, leave 0 for default." - top_delta="0" width="64" /> <text type="string" length="1" - bottom_delta="0" follows="left|top" height="16" layout="topleft" - left_delta="70" - name="pixels" - right="-10"> - pixels + left_pad="5" + name="pixels"> + px high </text> <text type="string" @@ -1851,15 +1847,15 @@ Texture: layout="topleft" left="10" name="Options:" - top="237" - width="292"> + top_pad="10" + width="100"> Options: </text> <check_box height="16" label="Loop" layout="topleft" - left_delta="70" + left_pad="10" name="media_loop" tool_tip="Play media in a loop. When the media has finished playing, it will restart from the beginning." top_delta="0" @@ -1867,9 +1863,9 @@ Texture: </panel> <panel border="true" - follows="left|top|right|bottom" + follows="all" height="363" - label="Audio" + label="Sound" layout="topleft" left_delta="0" help_topic="land_audio_tab" @@ -1971,7 +1967,7 @@ Texture: </panel> <panel border="true" - follows="left|top|right|bottom" + follows="all" height="333" label="Access" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_activeim.xml b/indra/newview/skins/default/xui/en/floater_activeim.xml index f81250e7b9..1bc9cde044 100644 --- a/indra/newview/skins/default/xui/en/floater_activeim.xml +++ b/indra/newview/skins/default/xui/en/floater_activeim.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" name="floater_activeim" help_topic="floater_activeim" title="ACTIVE IM" diff --git a/indra/newview/skins/default/xui/en/floater_animation_preview.xml b/indra/newview/skins/default/xui/en/floater_animation_preview.xml index 11773c34dc..ab3d5722f0 100644 --- a/indra/newview/skins/default/xui/en/floater_animation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_animation_preview.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" height="556" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_auction.xml b/indra/newview/skins/default/xui/en/floater_auction.xml index fb0994b4cd..aae6508041 100644 --- a/indra/newview/skins/default/xui/en/floater_auction.xml +++ b/indra/newview/skins/default/xui/en/floater_auction.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="412" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml index 0542d4509e..3f4f8b197f 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="350" layout="topleft" @@ -85,6 +86,52 @@ top="52" width="132" /> </panel> + <panel + border="none" + height="150" + label="Friends" + layout="topleft" + left="6" + help_topic="avatarpicker_friends_tab" + name="FriendsPanel" + top="150" + width="132"> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="10" + name="InstructSelectFriend" + top="15" + width="200"> + Select a friend(s): + </text> + <button + follows="top|right" + layout="topleft" + right="-5" + top ="5" + height="20" + width="20" + name="RefreshFriends" + picture_style="true" + image_overlay="Refresh_Off"> + <button.commit_callback + function="Refresh.FriendList"/> + </button> + <scroll_list + follows="all" + height="100" + border="false" + layout="topleft" + left="0" + name="Friends" + sort_column="0" + top_pad="5" + width="132" /> + </panel> <panel border="none" diff --git a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml index e677426ee5..4f2a36e518 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="950" layout="topleft" name="avatar_texture_debug" diff --git a/indra/newview/skins/default/xui/en/floater_beacons.xml b/indra/newview/skins/default/xui/en/floater_beacons.xml index a60064fb37..1c83799e72 100644 --- a/indra/newview/skins/default/xui/en/floater_beacons.xml +++ b/indra/newview/skins/default/xui/en/floater_beacons.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="225" layout="topleft" name="beacons" diff --git a/indra/newview/skins/default/xui/en/floater_build_options.xml b/indra/newview/skins/default/xui/en/floater_build_options.xml index 3e6845cfa5..bddbbdd3b2 100644 --- a/indra/newview/skins/default/xui/en/floater_build_options.xml +++ b/indra/newview/skins/default/xui/en/floater_build_options.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" follows="right" height="170" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml index ef6af28786..02958bee74 100644 --- a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_tear_off="false" height="310" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_bumps.xml b/indra/newview/skins/default/xui/en/floater_bumps.xml index d1f6706875..2917096f3c 100644 --- a/indra/newview/skins/default/xui/en/floater_bumps.xml +++ b/indra/newview/skins/default/xui/en/floater_bumps.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="180" layout="topleft" name="floater_bumps" diff --git a/indra/newview/skins/default/xui/en/floater_buy_contents.xml b/indra/newview/skins/default/xui/en/floater_buy_contents.xml index 718f83c9a2..aacc3ad8d0 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_contents.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="290" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml index 9b0b56d9cf..88712bda5e 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml @@ -1,12 +1,13 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <floater + legacy_header_height="18" can_minimize="false" height="275" layout="topleft" + title="Buy L$" name="buy currency" help_topic="buy_linden_dollars" single_instance="true" - title="Buy L$" width="350"> <floater.string name="buy_currency"> diff --git a/indra/newview/skins/default/xui/en/floater_buy_land.xml b/indra/newview/skins/default/xui/en/floater_buy_land.xml index 6d1c2c1cb9..8314549132 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_land.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_land.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" height="484" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_buy_object.xml b/indra/newview/skins/default/xui/en/floater_buy_object.xml index 7930622e54..49ea3f5dd1 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_object.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="290" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index a713cc32a0..1b69418013 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_dock="true" can_minimize="false" can_close="true" diff --git a/indra/newview/skins/default/xui/en/floater_choose_group.xml b/indra/newview/skins/default/xui/en/floater_choose_group.xml index 371e239fdb..8b34fda96c 100644 --- a/indra/newview/skins/default/xui/en/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/en/floater_choose_group.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="258" layout="topleft" name="groups" diff --git a/indra/newview/skins/default/xui/en/floater_color_picker.xml b/indra/newview/skins/default/xui/en/floater_color_picker.xml index f2146339a7..686b8dc40f 100644 --- a/indra/newview/skins/default/xui/en/floater_color_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_color_picker.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" follows="left|top" height="380" diff --git a/indra/newview/skins/default/xui/en/floater_critical.xml b/indra/newview/skins/default/xui/en/floater_critical.xml index 5475a1cf6a..7b5451553f 100644 --- a/indra/newview/skins/default/xui/en/floater_critical.xml +++ b/indra/newview/skins/default/xui/en/floater_critical.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_close="false" can_minimize="false" height="500" diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml index 57f5800f2c..07d76f4810 100644 --- a/indra/newview/skins/default/xui/en/floater_customize.xml +++ b/indra/newview/skins/default/xui/en/floater_customize.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" follows="left|top" height="540" diff --git a/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml index b044cd41e6..b8fa104352 100644 --- a/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml +++ b/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="275" layout="topleft" name="Day Cycle Floater" diff --git a/indra/newview/skins/default/xui/en/floater_device_settings.xml b/indra/newview/skins/default/xui/en/floater_device_settings.xml index 8901608374..2b23980423 100644 --- a/indra/newview/skins/default/xui/en/floater_device_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_device_settings.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="260" layout="topleft" name="floater_device_settings" diff --git a/indra/newview/skins/default/xui/en/floater_env_settings.xml b/indra/newview/skins/default/xui/en/floater_env_settings.xml index cecd6c4ef7..7c22311f66 100644 --- a/indra/newview/skins/default/xui/en/floater_env_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_env_settings.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="150" layout="topleft" name="Environment Editor Floater" diff --git a/indra/newview/skins/default/xui/en/floater_first_time_tip.xml b/indra/newview/skins/default/xui/en/floater_first_time_tip.xml index 4975111111..e4ac8fed77 100644 --- a/indra/newview/skins/default/xui/en/floater_first_time_tip.xml +++ b/indra/newview/skins/default/xui/en/floater_first_time_tip.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_close="true" can_minimize="false" height="250" diff --git a/indra/newview/skins/default/xui/en/floater_font_test.xml b/indra/newview/skins/default/xui/en/floater_font_test.xml index 66c207603b..8b14f691d6 100644 --- a/indra/newview/skins/default/xui/en/floater_font_test.xml +++ b/indra/newview/skins/default/xui/en/floater_font_test.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="800" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_gesture.xml b/indra/newview/skins/default/xui/en/floater_gesture.xml index 7346c81e79..128d518e12 100644 --- a/indra/newview/skins/default/xui/en/floater_gesture.xml +++ b/indra/newview/skins/default/xui/en/floater_gesture.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="465" name="gestures" diff --git a/indra/newview/skins/default/xui/en/floater_god_tools.xml b/indra/newview/skins/default/xui/en/floater_god_tools.xml index 02754b25dd..97cb6e259c 100644 --- a/indra/newview/skins/default/xui/en/floater_god_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_god_tools.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="384" layout="topleft" name="godtools floater" diff --git a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml index fe04d1f627..cd98f21918 100644 --- a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="224" layout="topleft" name="Hardware Settings Floater" @@ -131,7 +132,7 @@ layout="topleft" left="10" max_val="4096" - name="GrapicsCardTextureMemory" + name="GraphicsCardTextureMemory" tool_tip="Amount of memory to allocate for textures. Defaults to video card memory. Reducing this may improve performance but may also make textures blurry." top_pad="10" width="300" /> diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml index 512b4c85a1..d2fe8d0e6d 100644 --- a/indra/newview/skins/default/xui/en/floater_help_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_hud.xml b/indra/newview/skins/default/xui/en/floater_hud.xml index 23e0ef50fd..6e8950c49a 100644 --- a/indra/newview/skins/default/xui/en/floater_hud.xml +++ b/indra/newview/skins/default/xui/en/floater_hud.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" height="292" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 0037c6ef04..d9c3ff77d9 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" background_visible="true" follows="left|top|right|bottom" height="250" diff --git a/indra/newview/skins/default/xui/en/floater_image_preview.xml b/indra/newview/skins/default/xui/en/floater_image_preview.xml index 4e4fe97e62..2562daf4b3 100644 --- a/indra/newview/skins/default/xui/en/floater_image_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_image_preview.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" height="440" layout="topleft" 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 95e4247a05..dcb93c6e2f 100644 --- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml +++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_close="false" can_minimize="false" can_tear_off="false" diff --git a/indra/newview/skins/default/xui/en/floater_inspect.xml b/indra/newview/skins/default/xui/en/floater_inspect.xml index 339604e658..9f7723c51b 100644 --- a/indra/newview/skins/default/xui/en/floater_inspect.xml +++ b/indra/newview/skins/default/xui/en/floater_inspect.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="300" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml index ace296b439..6da4f9e6f3 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory.xml @@ -1,36 +1,45 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - auto_tile="true" - can_resize="true" - height="563" - layout="topleft" - min_height="150" - min_width="240" - name="Inventory" - help_topic="inventory" - save_rect="true" - save_visibility="true" - single_instance="true" - title="Inventory" - width="467"> - <floater.string - name="TitleFetching"> - Things (Fetching [ITEM_COUNT] Items...) [FILTER] - </floater.string> - <floater.string - name="TitleCompleted"> - Things ([ITEM_COUNT] Items) [FILTER] - </floater.string> -<panel - bottom="560" - class="panel_main_inventory" - filename="panel_main_inventory.xml" - follows="all" - layout="topleft" - left="0" - label="Inventory Panel" - name="Inventory Panel" - top="15" - width="467"> -</panel> -</floater> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ can_resize="true"
+ height="563"
+ layout="topleft"
+ min_height="150"
+ min_width="240"
+ name="Inventory"
+ help_topic="inventory"
+ save_rect="true"
+ save_visibility="true"
+ single_instance="true"
+ title="Inventory"
+ width="467">
+ <floater.string
+ name="Title">
+ Inventory
+ </floater.string>
+ <floater.string
+ name="TitleFetching">
+ Inventory (Fetching [ITEM_COUNT] Items...) [FILTER]
+ </floater.string>
+ <floater.string
+ name="TitleCompleted">
+ Inventory ([ITEM_COUNT] Items) [FILTER]
+ </floater.string>
+ <floater.string
+ name="Fetched">
+ Fetched
+ </floater.string>
+<panel
+ bottom="560"
+ class="panel_main_inventory"
+ filename="panel_main_inventory.xml"
+ follows="all"
+ layout="topleft"
+ left="0"
+ label="Inventory Panel"
+ name="Inventory Panel"
+ top="15"
+ width="467">
+</panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml index e3e2decef7..4f0609c7f8 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" auto_tile="true" height="340" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml index 6556a14730..0042f97a8e 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" height="408" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_joystick.xml b/indra/newview/skins/default/xui/en/floater_joystick.xml index c0bcfd2271..e2da059ace 100644 --- a/indra/newview/skins/default/xui/en/floater_joystick.xml +++ b/indra/newview/skins/default/xui/en/floater_joystick.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="500" layout="topleft" name="Joystick" diff --git a/indra/newview/skins/default/xui/en/floater_lagmeter.xml b/indra/newview/skins/default/xui/en/floater_lagmeter.xml index 2966b47232..d98fdc5118 100644 --- a/indra/newview/skins/default/xui/en/floater_lagmeter.xml +++ b/indra/newview/skins/default/xui/en/floater_lagmeter.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="150" layout="topleft" name="floater_lagmeter" diff --git a/indra/newview/skins/default/xui/en/floater_land_holdings.xml b/indra/newview/skins/default/xui/en/floater_land_holdings.xml index dbafa56035..46d74b6aff 100644 --- a/indra/newview/skins/default/xui/en/floater_land_holdings.xml +++ b/indra/newview/skins/default/xui/en/floater_land_holdings.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="400" layout="topleft" name="land holdings floater" diff --git a/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml index dc6c8302a0..93bbb0107e 100644 --- a/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml +++ b/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" bevel_style="none" border_style="line" can_resize="true" diff --git a/indra/newview/skins/default/xui/en/floater_lsl_guide.xml b/indra/newview/skins/default/xui/en/floater_lsl_guide.xml index fd2ee6ce5c..4dcf168605 100644 --- a/indra/newview/skins/default/xui/en/floater_lsl_guide.xml +++ b/indra/newview/skins/default/xui/en/floater_lsl_guide.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" follows="left|top" height="400" diff --git a/indra/newview/skins/default/xui/en/floater_map.xml b/indra/newview/skins/default/xui/en/floater_map.xml index a2b2e1ddf3..7b4c5f38a1 100644 --- a/indra/newview/skins/default/xui/en/floater_map.xml +++ b/indra/newview/skins/default/xui/en/floater_map.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" follows="top|right" height="225" diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml index ad2c50c6d9..b11892be74 100644 --- a/indra/newview/skins/default/xui/en/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="440" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_media_settings.xml b/indra/newview/skins/default/xui/en/floater_media_settings.xml index b96573b32a..4218c15408 100644 --- a/indra/newview/skins/default/xui/en/floater_media_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_media_settings.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater +<floater + legacy_header_height="18" bottom="-666" can_close="true" can_drag_on_left="false" diff --git a/indra/newview/skins/default/xui/en/floater_mem_leaking.xml b/indra/newview/skins/default/xui/en/floater_mem_leaking.xml index bd83da02aa..560acafd4f 100644 --- a/indra/newview/skins/default/xui/en/floater_mem_leaking.xml +++ b/indra/newview/skins/default/xui/en/floater_mem_leaking.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" follows="left|top" height="175" diff --git a/indra/newview/skins/default/xui/en/floater_moveview.xml b/indra/newview/skins/default/xui/en/floater_moveview.xml index 745385f153..02cbef5987 100644 --- a/indra/newview/skins/default/xui/en/floater_moveview.xml +++ b/indra/newview/skins/default/xui/en/floater_moveview.xml @@ -1,8 +1,9 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_dock="true" can_close="true" - can_minimize="true" + can_minimize="false" center_horiz="true" follows="bottom" height="110" @@ -37,7 +38,7 @@ Fly Backwards (press Down Arrow or S) </string> <panel - border="true" + border="false" height="83" follows="left|top" layout="topleft" @@ -135,7 +136,7 @@ </panel> <!-- Width and height of this panel should be synchronized with panel_stand_stop_flying.xml --> <panel - border="true" + border="false" height="27" layout="topleft" left="0" diff --git a/indra/newview/skins/default/xui/en/floater_mute_object.xml b/indra/newview/skins/default/xui/en/floater_mute_object.xml index 06a03ff340..33b1dac8a5 100644 --- a/indra/newview/skins/default/xui/en/floater_mute_object.xml +++ b/indra/newview/skins/default/xui/en/floater_mute_object.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" height="130" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_my_friends.xml b/indra/newview/skins/default/xui/en/floater_my_friends.xml index 0ca4fc825a..689221b9c7 100644 --- a/indra/newview/skins/default/xui/en/floater_my_friends.xml +++ b/indra/newview/skins/default/xui/en/floater_my_friends.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_close="false" can_resize="true" height="390" 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 d24d1b7064..65dd4e74ff 100644 --- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater +<floater + legacy_header_height="18" can_minimize="true" can_tear_off="false" can_resize="false" diff --git a/indra/newview/skins/default/xui/en/floater_notification.xml b/indra/newview/skins/default/xui/en/floater_notification.xml index cd88ec2f3f..f9cb22055a 100644 --- a/indra/newview/skins/default/xui/en/floater_notification.xml +++ b/indra/newview/skins/default/xui/en/floater_notification.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="200" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_notifications_console.xml b/indra/newview/skins/default/xui/en/floater_notifications_console.xml index 3783417cdb..03a2aad96d 100644 --- a/indra/newview/skins/default/xui/en/floater_notifications_console.xml +++ b/indra/newview/skins/default/xui/en/floater_notifications_console.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="500" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_openobject.xml b/indra/newview/skins/default/xui/en/floater_openobject.xml index 1c9fc3893e..af8aadf0e0 100644 --- a/indra/newview/skins/default/xui/en/floater_openobject.xml +++ b/indra/newview/skins/default/xui/en/floater_openobject.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" default_tab_group="1" height="350" diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml index 69525d48d2..b4becfa022 100644 --- a/indra/newview/skins/default/xui/en/floater_pay.xml +++ b/indra/newview/skins/default/xui/en/floater_pay.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" height="185" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_pay_object.xml b/indra/newview/skins/default/xui/en/floater_pay_object.xml index acff55386b..8d230023cc 100644 --- a/indra/newview/skins/default/xui/en/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/en/floater_pay_object.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" height="220" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml index f65bb6f32f..eb0c22b9c4 100644 --- a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml +++ b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="180" layout="topleft" name="perm prefs" diff --git a/indra/newview/skins/default/xui/en/floater_post_process.xml b/indra/newview/skins/default/xui/en/floater_post_process.xml index 571f4149f0..46554beede 100644 --- a/indra/newview/skins/default/xui/en/floater_post_process.xml +++ b/indra/newview/skins/default/xui/en/floater_post_process.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="400" layout="topleft" name="Post-Process Floater" diff --git a/indra/newview/skins/default/xui/en/floater_postcard.xml b/indra/newview/skins/default/xui/en/floater_postcard.xml index d93cad6dbd..b13bd1740c 100644 --- a/indra/newview/skins/default/xui/en/floater_postcard.xml +++ b/indra/newview/skins/default/xui/en/floater_postcard.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" auto_tile="true" can_minimize="false" can_resize="true" diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml index 90a77b22b6..d2a2a7ce02 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" center_horiz="true" center_vert="true" default_tab_group="1" diff --git a/indra/newview/skins/default/xui/en/floater_preview_animation.xml b/indra/newview/skins/default/xui/en/floater_preview_animation.xml index e34b87dbba..3b84358484 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_animation.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_animation.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" auto_tile="true" height="85" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_preview_classified.xml b/indra/newview/skins/default/xui/en/floater_preview_classified.xml index 07167c3ae4..7c8c6d7207 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_classified.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_classified.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" auto_tile="true" height="510" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_preview_event.xml b/indra/newview/skins/default/xui/en/floater_preview_event.xml index 77fbe7c060..f5ab8c95d7 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_event.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_event.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" auto_tile="true" height="510" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml index 11c4e5d8fb..4f3978a5e3 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" auto_tile="true" height="460" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml index 43e4f8a348..fc838f27b4 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" follows="left|top" height="155" diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml index 606ae1a82a..b489ae2e77 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" follows="left|top" height="90" diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml index 4b4f611b59..8a07f3ad1e 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" follows="left|top" height="155" diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml index d2b8455eab..3797055054 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" auto_tile="true" can_resize="true" default_tab_group="1" diff --git a/indra/newview/skins/default/xui/en/floater_preview_sound.xml b/indra/newview/skins/default/xui/en/floater_preview_sound.xml index 7a868a1fe9..95347f0dff 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_sound.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_sound.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" auto_tile="true" height="85" layout="topleft" 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 32f71da61a..e7abfb075a 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_texture.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_texture.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" auto_tile="true" can_resize="true" follows="left|bottom" diff --git a/indra/newview/skins/default/xui/en/floater_region_info.xml b/indra/newview/skins/default/xui/en/floater_region_info.xml index 3fadc15616..ae01d0bdf4 100644 --- a/indra/newview/skins/default/xui/en/floater_region_info.xml +++ b/indra/newview/skins/default/xui/en/floater_region_info.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="512" help_topic="regioninfo" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml index 884532c7a3..88f09b521c 100644 --- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="580" layout="topleft" name="floater_report_abuse" diff --git a/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml index 2085b74a55..0029fcb09b 100644 --- a/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml +++ b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" follows="left|top|right|bottom" height="200" diff --git a/indra/newview/skins/default/xui/en/floater_script_preview.xml b/indra/newview/skins/default/xui/en/floater_script_preview.xml index a415239867..c29a2f4516 100644 --- a/indra/newview/skins/default/xui/en/floater_script_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_script_preview.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" auto_tile="true" can_resize="true" height="550" diff --git a/indra/newview/skins/default/xui/en/floater_script_queue.xml b/indra/newview/skins/default/xui/en/floater_script_queue.xml index 467dcfae20..8a44252426 100644 --- a/indra/newview/skins/default/xui/en/floater_script_queue.xml +++ b/indra/newview/skins/default/xui/en/floater_script_queue.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" auto_tile="true" can_resize="true" height="400" diff --git a/indra/newview/skins/default/xui/en/floater_script_search.xml b/indra/newview/skins/default/xui/en/floater_script_search.xml index 545abc39a2..79c4438dd6 100644 --- a/indra/newview/skins/default/xui/en/floater_script_search.xml +++ b/indra/newview/skins/default/xui/en/floater_script_search.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" default_tab_group="1" height="120" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_search.xml b/indra/newview/skins/default/xui/en/floater_search.xml index 296cde92e3..2f4d7c50a1 100644 --- a/indra/newview/skins/default/xui/en/floater_search.xml +++ b/indra/newview/skins/default/xui/en/floater_search.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_select_key.xml b/indra/newview/skins/default/xui/en/floater_select_key.xml index b89af0ef3e..31d133ff9b 100644 --- a/indra/newview/skins/default/xui/en/floater_select_key.xml +++ b/indra/newview/skins/default/xui/en/floater_select_key.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" border="true" can_close="false" can_minimize="false" diff --git a/indra/newview/skins/default/xui/en/floater_sell_land.xml b/indra/newview/skins/default/xui/en/floater_sell_land.xml index 652ed96192..8fedd0a89f 100644 --- a/indra/newview/skins/default/xui/en/floater_sell_land.xml +++ b/indra/newview/skins/default/xui/en/floater_sell_land.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" height="450" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_settings_debug.xml b/indra/newview/skins/default/xui/en/floater_settings_debug.xml index b7779687ec..02b3cee97c 100644 --- a/indra/newview/skins/default/xui/en/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/en/floater_settings_debug.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" height="215" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 551f570b52..4f2be37ade 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" follows="left|top" height="526" diff --git a/indra/newview/skins/default/xui/en/floater_sound_preview.xml b/indra/newview/skins/default/xui/en/floater_sound_preview.xml index 3b1eae9293..6145b722f1 100644 --- a/indra/newview/skins/default/xui/en/floater_sound_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_sound_preview.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="190" layout="topleft" name="Sound Preview" diff --git a/indra/newview/skins/default/xui/en/floater_statistics.xml b/indra/newview/skins/default/xui/en/floater_statistics.xml index 653bc942e5..ab783b0735 100644 --- a/indra/newview/skins/default/xui/en/floater_statistics.xml +++ b/indra/newview/skins/default/xui/en/floater_statistics.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" follows="right|top" height="392" diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml index 205e6efe70..bdc2874281 100644 --- a/indra/newview/skins/default/xui/en/floater_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_stats.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" follows="top|right" height="400" diff --git a/indra/newview/skins/default/xui/en/floater_sys_well.xml b/indra/newview/skins/default/xui/en/floater_sys_well.xml index aef5707fd4..e1f07a49e7 100644 --- a/indra/newview/skins/default/xui/en/floater_sys_well.xml +++ b/indra/newview/skins/default/xui/en/floater_sys_well.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater +<floater + legacy_header_height="18" bevel_style="in" left="0" top="0" diff --git a/indra/newview/skins/default/xui/en/floater_telehub.xml b/indra/newview/skins/default/xui/en/floater_telehub.xml index 95de27e0ea..faf1a378f2 100644 --- a/indra/newview/skins/default/xui/en/floater_telehub.xml +++ b/indra/newview/skins/default/xui/en/floater_telehub.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="250" layout="topleft" name="telehub" diff --git a/indra/newview/skins/default/xui/en/floater_test_button.xml b/indra/newview/skins/default/xui/en/floater_test_button.xml index ce17873a67..89a1ddda99 100644 --- a/indra/newview/skins/default/xui/en/floater_test_button.xml +++ b/indra/newview/skins/default/xui/en/floater_test_button.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="500" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_test_checkbox.xml b/indra/newview/skins/default/xui/en/floater_test_checkbox.xml index 66a5b9267d..9977e85a9d 100644 --- a/indra/newview/skins/default/xui/en/floater_test_checkbox.xml +++ b/indra/newview/skins/default/xui/en/floater_test_checkbox.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_test_combobox.xml b/indra/newview/skins/default/xui/en/floater_test_combobox.xml index 956d5669b8..317d8f5ba8 100644 --- a/indra/newview/skins/default/xui/en/floater_test_combobox.xml +++ b/indra/newview/skins/default/xui/en/floater_test_combobox.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml index ce20b03919..c954607ffe 100644 --- a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml +++ b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="false" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_test_layout.xml b/indra/newview/skins/default/xui/en/floater_test_layout.xml index 209859bb29..c6acb7c96e 100644 --- a/indra/newview/skins/default/xui/en/floater_test_layout.xml +++ b/indra/newview/skins/default/xui/en/floater_test_layout.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="500" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_test_line_editor.xml b/indra/newview/skins/default/xui/en/floater_test_line_editor.xml index 251ca4c9bf..e017d404c6 100644 --- a/indra/newview/skins/default/xui/en/floater_test_line_editor.xml +++ b/indra/newview/skins/default/xui/en/floater_test_line_editor.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_test_list_view.xml b/indra/newview/skins/default/xui/en/floater_test_list_view.xml index 98d6d5bda7..1d2086d9bc 100644 --- a/indra/newview/skins/default/xui/en/floater_test_list_view.xml +++ b/indra/newview/skins/default/xui/en/floater_test_list_view.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml b/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml index dd551b6d51..c6b4cca6b9 100644 --- a/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="200" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml b/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml index 35190c0e1a..7ef2d97cdc 100644 --- a/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml +++ b/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_test_slider.xml b/indra/newview/skins/default/xui/en/floater_test_slider.xml index 3545f88df7..57d8e686ce 100644 --- a/indra/newview/skins/default/xui/en/floater_test_slider.xml +++ b/indra/newview/skins/default/xui/en/floater_test_slider.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_test_spinner.xml b/indra/newview/skins/default/xui/en/floater_test_spinner.xml index c4e5bc9e99..3c44a4884d 100644 --- a/indra/newview/skins/default/xui/en/floater_test_spinner.xml +++ b/indra/newview/skins/default/xui/en/floater_test_spinner.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml index c33ab8aa70..f39d27761c 100644 --- a/indra/newview/skins/default/xui/en/floater_test_textbox.xml +++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_test_widgets.xml b/indra/newview/skins/default/xui/en/floater_test_widgets.xml index cc0fc34dd5..129fd863dd 100644 --- a/indra/newview/skins/default/xui/en/floater_test_widgets.xml +++ b/indra/newview/skins/default/xui/en/floater_test_widgets.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<!-- Sample "floater" window with examples of common widgets. +<!-- Sample "floater" window with examples of common widgets. Notes: XML UI (XUI) files use spaces for indentation, not tabs. @@ -15,17 +15,18 @@ Otherwise specify location with left and top attributes. --> <floater - can_dock="true" + legacy_header_height="18" + can_dock="true" can_resize="true" title="Test Floater" height="500" - min_width="850" - min_height="500" + min_width="850" + min_height="500" layout="topleft" name="floater_test_widgets" help_topic="floater_test_widgets" width="850"> - + <!-- Strings are used by C++ code for localization. They are not visible unless the C++ code uses them to fill in another widget. --> <floater.string @@ -34,15 +35,15 @@ <floater.string name="other_string" value="Other String" /> - + <!-- Floaters can contain drop-down menus. The menu_bar widget contains the inividual menus. The width is automatically computed to fit the labels. --> <menu_bar height="18" layout="topleft" - follows="top|left" - tool_tip="menu" + follows="top|left" + tool_tip="menu" left="2" name="test_menu_bar" top="16"> @@ -70,7 +71,7 @@ name="test_menu_item_2" /> </menu> </menu_bar> - + <!-- "text" is one or more read-only lines of text. It can be made clickable but this requires C++ code support. URLs are not automatically underlined. --> @@ -84,27 +85,27 @@ </text> <!-- First column --> - + <button height="20" - follows="top|left" + follows="top|left" label="Button" layout="topleft" left_delta="0" name="test_button" - tool_tip="button" + tool_tip="button" top="80" - width="100" /> + width="100" /> <!-- "flyout_button" is a button that can spawn a menu --> <flyout_button - follows="top|left" + follows="top|left" height="20" label="Flyout" layout="topleft" left_delta="0" name="fly_btn" top_pad="15" - tool_tip="flyout button" + tool_tip="flyout button" width="100"> <flyout_button.item label="Item 1" @@ -120,19 +121,19 @@ bottom_delta="35" label="Checkbox" layout="topleft" - tool_tip="checkbox" + tool_tip="checkbox" name="test_checkbox" /> <!-- "combo_box" is a pop-menu of items. Optionally the box itself can contain a general purpose line input editor, allowing the user to provide input that is not a list item. --> <combo_box bottom_delta="35" - follows="top|left" + follows="top|left" height="16" width="150" label="Combobox" layout="topleft" - tool_tip="combo box" + tool_tip="combo box" name="test_combo_box"> <combo_box.item name="item1" @@ -148,21 +149,21 @@ image_name="icon_avatar_online.tga" layout="topleft" left_delta="0" - tool_tip="icon" + tool_tip="icon" name="test_icon" top_pad="40" width="16" /> - <!-- "line_editor" allows a single line of editable text input. + <!-- "line_editor" allows a single line of editable text input. The contents of this XML node are used as the initial value for the text. --> <line_editor height="20" - follows="top|left" + follows="top|left" layout="topleft" left_delta="0" name="test_line_editor" top_pad="20" - tool_tip="line editor" + tool_tip="line editor" width="200"> Line Editor Sample Text </line_editor> @@ -175,18 +176,18 @@ layout="topleft" left_delta="0" name="search editor" - tool_tip="search editor" + tool_tip="search editor" top_pad="30" width="200" /> <!-- "progress_bar" percent completed gets set in C++ code --> <progress_bar height="16" - follows="top|left" + follows="top|left" layout="topleft" left_delta="0" name="test_progress_bar" top_pad="30" - tool_tip="progress bar" + tool_tip="progress bar" width="200" /> <!-- "stat_view" is a container for statistics graphs. It is only used for debugging/diagnostic displays. --> @@ -198,10 +199,10 @@ name="axis_view" show_label="true" top_pad="30" - tool_tip="stat view" + tool_tip="stat view" width="200"> <stat_bar - width="100" + width="100" bar_max="100" bottom_delta="30" label="Test Stat" @@ -210,9 +211,9 @@ bar_min="20" name="test_stat_bar" /> </stat_view> - + <!-- New column --> - + <!-- "radio_group" is a set of mutually exclusive choices, like the buttons on a car radio that allow a single radio station to be chosen. --> <radio_group @@ -220,7 +221,7 @@ layout="topleft" left_pad="90" name="size_radio_group" - tool_tip="radio group" + tool_tip="radio group" top="80" width="200"> <radio_item @@ -236,10 +237,10 @@ <!-- "scroll_list" is a scrolling list of columnar data. --> <scroll_list bottom_delta="100" - follows="top|left" + follows="top|left" height="80" draw_heading="true" - tool_tip="scroll list" + tool_tip="scroll list" layout="topleft"> <scroll_list.columns dynamic_width="true" @@ -261,29 +262,29 @@ <!-- "slider" is a horizontal input widget for numerical data. --> <slider bottom_delta="45" - follows="top|left" + follows="top|left" layout="topleft" min_val="0" max_val="100" initial_value="20" label="Slider" name="test_slider" - tool_tip="slider" + tool_tip="slider" width="200" /> <!-- "spinner" is a numerical input widget with an up and down arrow to change the value. --> <spinner bottom_delta="35" - follows="top|left" + follows="top|left" label="Spinner" layout="topleft" - label_width="45" - name="test_spinner" + label_width="45" + name="test_spinner" tool_tip="spinner"/> <text bottom_delta="50" - follows="top|left" - font.name="SansSerifSmall" + follows="top|left" + font.name="SansSerifSmall" font.style = "UNDERLINE" layout="topleft" name="test_text" @@ -292,23 +293,23 @@ </text> <text top_pad="10" - follows="top|left" + follows="top|left" layout="topleft" - width="60" - use_ellipses="true" + width="60" + use_ellipses="true" name="test_text" tool_tip="text"> Truncated text here </text> - <!-- "text_editor" is a multi-line text input widget, similar to + <!-- "text_editor" is a multi-line text input widget, similar to textarea in HTML. --> <text_editor height="40" - follows="top|left|bottom" + follows="top|left|bottom" layout="topleft" left_delta="0" name="test_text_editor" - tool_tip="text editor" + tool_tip="text editor" top_pad="25" width="200"> Text Editor @@ -329,17 +330,19 @@ many line to actually fit </text> <!-- And a third column --> - + <!-- "tab_container" is a holder for multiple panels of UI widgets. Tabs can appear at the top, bottom, or left of the container. --> <tab_container follows="all" height="400" + halign="center" layout="topleft" left="575" name="group_tab_container" tab_position="top" - tool_tip="tab container" + tab_height="20" + tool_tip="tab container" top="80" width="250"> <!-- "panel" is a container for widgets. It is automatically resized to diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml index f2b701b88d..0a1f6e0e29 100644 --- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" can_resize="true" height="290" diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 93b50f6b78..845f68a7ee 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1,8 +1,11 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" follows="left|top|right" height="570" layout="topleft" + bg_opaque_image="Window_NoTitle_Foreground" + bg_alpha_image="Window_NoTitle_Background" name="toolbox floater" help_topic="toolbox_floater" save_rect="true" @@ -746,6 +749,7 @@ <tab_container follows="left|top" height="400" + halign="center" left="0" name="Object Info Tabs" tab_max_width="55" @@ -2735,8 +2739,19 @@ <button.commit_callback function="BuildTool.EditMedia"/> </button> - - <button + <web_browser + visible="false" + enabled="false" + border_visible="true" + bottom_delta="0" + follows="top|left" + left="0" + name="title_media" + width="4" + height="4" + start_url="about:blank" + decouple_texture_size="true" /> + <button follows="left|top" font="SansSerifSmall" height="19" diff --git a/indra/newview/skins/default/xui/en/floater_top_objects.xml b/indra/newview/skins/default/xui/en/floater_top_objects.xml index 07ffc204f9..2f53422d51 100644 --- a/indra/newview/skins/default/xui/en/floater_top_objects.xml +++ b/indra/newview/skins/default/xui/en/floater_top_objects.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="350" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_tos.xml b/indra/newview/skins/default/xui/en/floater_tos.xml index 54facbb659..4e2cce1428 100644 --- a/indra/newview/skins/default/xui/en/floater_tos.xml +++ b/indra/newview/skins/default/xui/en/floater_tos.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_close="false" can_minimize="false" height="500" diff --git a/indra/newview/skins/default/xui/en/floater_ui_preview.xml b/indra/newview/skins/default/xui/en/floater_ui_preview.xml index acd770cd38..380e51977f 100644 --- a/indra/newview/skins/default/xui/en/floater_ui_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_ui_preview.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" height="640" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_url_entry.xml b/indra/newview/skins/default/xui/en/floater_url_entry.xml index 6c1fb65bdd..1ab42cb140 100644 --- a/indra/newview/skins/default/xui/en/floater_url_entry.xml +++ b/indra/newview/skins/default/xui/en/floater_url_entry.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" height="87" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_water.xml b/indra/newview/skins/default/xui/en/floater_water.xml index a860b1038c..af3606fd1c 100644 --- a/indra/newview/skins/default/xui/en/floater_water.xml +++ b/indra/newview/skins/default/xui/en/floater_water.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="240" layout="topleft" name="Water Floater" @@ -61,10 +62,12 @@ <tab_container follows="left|top" height="180" + halign="center" layout="topleft" left="0" name="Water Tabs" tab_position="top" + tab_height="20" top="60" width="700"> <panel diff --git a/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml b/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml index ee67989d33..9a95e3dfef 100644 --- a/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml +++ b/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" border="true" can_close="false" can_minimize="false" diff --git a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml index 4f501b65f3..ef68d03a45 100644 --- a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml +++ b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_minimize="false" height="108" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_windlight_options.xml b/indra/newview/skins/default/xui/en/floater_windlight_options.xml index 2b3bc5f11a..2c09e82f08 100644 --- a/indra/newview/skins/default/xui/en/floater_windlight_options.xml +++ b/indra/newview/skins/default/xui/en/floater_windlight_options.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" height="220" layout="topleft" name="WindLight floater" @@ -70,10 +71,12 @@ <tab_container follows="left|top" height="160" + halign="center" layout="topleft" left="0" name="WindLight Tabs" tab_position="top" + tab_height="20" top="60" width="700"> <panel 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 f37c0e9022..93755fa253 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater + legacy_header_height="18" can_resize="true" center_horiz="true" center_vert="true" diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml index b261281c64..65dfb13f4a 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -18,7 +18,7 @@ </os> </font> - <font name="SansSerifBold" + <font name="SansSerifBold" comment="Name of bold sans-serif font"> <file>DejaVuSans-Bold.ttf</file> <os name="Windows"> @@ -39,20 +39,20 @@ </os> </font> - <font name="SansSerif" - comment="Name of bold sans-serif font" + <font name="SansSerif" + comment="Name of bold sans-serif font" font_style="BOLD"> <file>DejaVuSans-Bold.ttf</file> </font> - <font name="SansSerif" - comment="Name of italic sans-serif font" + <font name="SansSerif" + comment="Name of italic sans-serif font" font_style="ITALIC"> <file>DejaVuSans-Oblique.ttf</file> </font> - <font name="SansSerif" - comment="Name of bold italic sans-serif font" + <font name="SansSerif" + comment="Name of bold italic sans-serif font" font_style="BOLD|ITALIC"> <file>DejaVuSans-BoldOblique.ttf</file> </font> @@ -140,11 +140,11 @@ <font_size name="Monospace" comment="Size for monospaced font (points, or 1/72 of an inch)" - size="9.0" + size="8.0" /> <font_size name="Huge" comment="Size of huge font (points, or 1/72 of an inch)" - size="16.0" + size="15.0" /> <font_size name="Large" comment="Size of large font (points, or 1/72 of an inch)" @@ -158,7 +158,6 @@ /> <font_size name="Small" comment="Size of small font (points, or 1/72 of an inch)" - size="8.0" + size="7.8" /> </fonts> - diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index 181c80ebc7..6b13e2f1c7 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -4,8 +4,9 @@ Single instance - only have one at a time, recycle it each spawn --> <floater + legacy_header_height="18" bevel_style="in" - bg_opaque_color="MouseGray" + bg_opaque_image="Inspector_Background" can_close="false" can_minimize="false" height="138" diff --git a/indra/newview/skins/default/xui/en/inspect_group.xml b/indra/newview/skins/default/xui/en/inspect_group.xml index 5b166e83b8..db12daa6e0 100644 --- a/indra/newview/skins/default/xui/en/inspect_group.xml +++ b/indra/newview/skins/default/xui/en/inspect_group.xml @@ -4,8 +4,9 @@ Single instance - only have one at a time, recycle it each spawn --> <floater + legacy_header_height="18" bevel_style="in" - bg_opaque_color="MouseGray" + bg_opaque_image="Inspector_Background" can_close="false" can_minimize="false" height="138" diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml index 73a7bef77d..fe492e0ae8 100644 --- a/indra/newview/skins/default/xui/en/inspect_object.xml +++ b/indra/newview/skins/default/xui/en/inspect_object.xml @@ -4,8 +4,9 @@ Single instance - only have one at a time, recycle it each spawn --> <floater + legacy_header_height="18" bevel_style="in" - bg_opaque_color="MouseGray" + bg_opaque_image="Inspector_Background" can_close="false" can_minimize="false" height="145" @@ -70,7 +71,7 @@ owner James Linden width="150"> L$300,000 </text> - <text + <text follows="all" height="30" left="8" @@ -83,24 +84,35 @@ This is a really long description for an object being as how it is at least 80 c </text> <!-- Overlapping buttons for all default actions. Show "Buy" if for sale, "Sit" if can sit, etc. --> + <text + follows="all" + height="15" + left_delta="0" + name="object_media_url" + top_pad="-5" + width="291" + max_length = "50" + use_ellipses="true" + word_wrap="true"/> + <button - follows="top|left" - font="SansSerif" - height="23" - label="Buy" - left="10" - name="buy_btn" - top="114" - width="100" /> + follows="top|left" + font="SansSerif" + height="20" + label="Buy" + left="10" + name="buy_btn" + top="114" + width="75" /> <button follows="top|left" font="SansSerif" - height="23" + height="20" label="Pay" left_delta="0" name="pay_btn" top_delta="0" - width="100" /> + width="75" /> <button follows="top|left" font="SansSerif" @@ -109,16 +121,16 @@ This is a really long description for an object being as how it is at least 80 c left_delta="0" name="take_free_copy_btn" top_delta="0" - width="100" /> + width="75" /> <button follows="top|left" font="SansSerifSmall" - height="23" + height="20" label="Touch" left_delta="0" name="touch_btn" top_delta="0" - width="100" /> + width="75" /> <button follows="top|left" font="SansSerif" @@ -127,17 +139,27 @@ This is a really long description for an object being as how it is at least 80 c left_delta="0" name="sit_btn" top_delta="0" - width="100" /> + width="75" /> <button follows="top|left" font="SansSerifSmall" - height="23" + height="20" label="Open" left_delta="0" name="open_btn" top_delta="0" - width="100" /> - <!-- non-overlapping buttons here --> + width="75" /> + <icon + name="secure_browsing" + image_name="map_infohub.tga" + left_delta="80" + width="16" + height="16" + top_delta="2" + tool_tip="Secure Browsing" + follows="left|top"/> + + <!-- non-overlapping buttons here --> <menu_button follows="top|left" height="18" diff --git a/indra/newview/skins/default/xui/en/menu_object_icon.xml b/indra/newview/skins/default/xui/en/menu_object_icon.xml new file mode 100644 index 0000000000..0c8a2af002 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_object_icon.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<menu + height="101" + layout="topleft" + left="100" + mouse_opaque="false" + name="Object Icon Menu" + top="724" + visible="false" + width="128"> + <menu_item_call + label="Object Profile..." + layout="topleft" + name="Object Profile"> + <menu_item_call.on_click + function="ObjectIcon.Action" + parameter="profile" /> + </menu_item_call> + <menu_item_call + label="Block..." + layout="topleft" + name="Block"> + <menu_item_call.on_click + function="ObjectIcon.Action" + parameter="block" /> + </menu_item_call> +</menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index a59a8b065f..3f63f493b1 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -167,6 +167,18 @@ function="Floater.Toggle" parameter="active_speakers" /> </menu_item_check> + <menu_item_check + label="Nearby Media" + layout="topleft" + name="Nearby Media" + shortcut="control|alt|N"> + <menu_item_check.on_check + function="Floater.Visible" + parameter="nearby_media" /> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="nearby_media" /> + </menu_item_check> <!--menu_item_check label="Block List" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index ac98907199..d51cb13093 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -13,7 +13,7 @@ <global name="implicitclosebutton"> Close </global> - + <template name="okbutton"> <form> <button @@ -154,7 +154,7 @@ No tutorial is currently available. icon="alertmodal.tga" name="BadInstallation" type="alertmodal"> - An error occurred while updating [APP_NAME]. Please download the latest version of the Viewer. http://get.secondlife.com + An error occurred while updating [APP_NAME]. Please [http://get.secondlife.com download the latest version] of the Viewer. <usetemplate name="okbutton" yestext="Ok"/> @@ -507,7 +507,7 @@ For L$[COST] you can enter this land ('[PARCEL_NAME]') for [TIME] hour notext="Cancel" yestext="OK"/> </notification> - + <notification icon="alertmodal.tga" name="SalePriceRestriction" @@ -664,7 +664,7 @@ Scripts must be allowed to run for weapons to work. icon="alertmodal.tga" name="MultipleFacesSelected" type="alertmodal"> -Multiple faces are currently selected. +Multiple faces are currently selected. If you continue this action, separate instances of media will be set on multiple faces of the object. To place the media on only one face, choose Select Texture and click on the desired face of that object then click Add. <usetemplate @@ -791,7 +791,7 @@ Oops! Something was left blank. You need to enter both the First and Last name of your avatar. You need an account to enter [SECOND_LIFE]. Would you like to create one now? - <url + <url option="0" name="url" openexternally = "1"> @@ -808,7 +808,7 @@ You need an account to enter [SECOND_LIFE]. Would you like to create one now? icon="alertmodal.tga" name="AddClassified" type="alertmodal"> -Classified ads appear in the 'Classified' section of the Search directory and on www.secondlife.com for one week. +Classified ads appear in the 'Classified' section of the Search directory and on [http://www.secondlife.com secondlife.com] for one week. Fill out your ad, then click 'Publish...' to add it to the directory. You'll be asked for a price to pay when clicking Publish. Paying more makes your ad appear higher in the list, and also appear higher when people search for keywords. @@ -1060,13 +1060,13 @@ There was a problem saving a compiled script due to the following reason: [REASO icon="alertmodal.tga" name="StartRegionEmpty" type="alertmodal"> -Oops, Your Start Region is not defined. -Please type the Region name in Start Location box or choose My Last Location or My Home as your Start Location. +Oops, Your Start Region is not defined. +Please type the Region name in Start Location box or choose My Last Location or My Home as your Start Location. <usetemplate name="okbutton" yestext="OK"/> </notification> - + <notification icon="alertmodal.tga" name="CouldNotStartStopScript" @@ -2409,7 +2409,7 @@ You can use [SECOND_LIFE] normally and other people will see you correctly. [APP_NAME] installation is complete. If this is your first time using [SECOND_LIFE], you will need to create an account before you can log in. -Return to www.secondlife.com to create a new account? +Return to [http://join.secondlife.com secondlife.com] to create a new account? <usetemplate name="okcancelbuttons" notext="Continue" @@ -2426,7 +2426,7 @@ You can either check your Internet connection and try again in a few minutes, cl <url option="1" name="url"> http://secondlife.com/support/ - </url> + </url> <form name="form"> <button default="true" @@ -2801,7 +2801,7 @@ Do you want to open your Web browser to view this content? icon="alertmodal.tga" name="WebLaunchJoinNow" type="alertmodal"> -Go to secondlife.com to manage your account? +Go to your [http://secondlife.com/account/ Dashboard] to manage your account? <usetemplate ignoretext="Launch my browser to manage my account" name="okcancelignore" @@ -3163,7 +3163,7 @@ Teleport to [PICK]? notext="Cancel" yestext="Teleport"/> </notification> - + <notification icon="alert.tga" label="Message everyone in your Estate" @@ -3657,7 +3657,7 @@ Default: off label="Bulk Change Content Permissions" name="HelpBulkPermission" type="alertmodal"> -The Bulk Permissions tool helps you to quickly change the permissions on multiple items in the contents of the selected object(s). However, please note that you are only setting permissions on the items in the Contents of the selected objects -- not permissions on the container object(s) themselves. +The Bulk Permissions tool helps you to quickly change the permissions on multiple items in the contents of the selected object(s). However, please note that you are only setting permissions on the items in the Contents of the selected objects -- not permissions on the container object(s) themselves. Also note, the permissions are not applied to the nested contents of any of the contained items. Your request only operates on items exactly one level deep. @@ -4251,7 +4251,7 @@ There are no items in this object that you are allowed to copy. icon="alertmodal.tga" name="WebLaunchAccountHistory" type="alertmodal"> -Go to secondlife.com to see your account history? +Go to your [http://secondlife.com/account/ Dashboard] to see your account history? <usetemplate ignoretext="Launch my browser to see my account history" name="okcancelignore" @@ -4288,14 +4288,9 @@ Are you sure you want to quit? icon="alertmodal.tga" name="HelpReportAbuseEmailLL" type="alertmodal"> -Use this tool to report violations of the Terms of Service and Community Standards. See: +Use this tool to report violations of the [http://secondlife.com/corporate/tos.php Terms of Service] and [http://secondlife.com/corporate/cs.php Community Standards]. -http://secondlife.com/corporate/tos.php -http://secondlife.com/corporate/cs.php - -All reported abuses of the Terms of Service and Community Standards are investigated and resolved. You can view the incident resolution on the Incident Report at: - -http://secondlife.com/support/incidentreport.php +All reported abuses are investigated and resolved. You can view the resolution by reading the [http://secondlife.com/support/incidentreport.php Incident Report]. <unique/> </notification> @@ -4363,9 +4358,9 @@ Dear Resident, You appear to be reporting intellectual property infringement. Please make sure you are reporting it correctly: -(1) The Abuse Process. You may submit an abuse report if you believe a Resident is exploiting the [SECOND_LIFE] permissions system, for example, by using CopyBot or similar copying tools, to infringe intellectual property rights. The Abuse Team investigates and issues appropriate disciplinary action for behavior that violates the [SECOND_LIFE] Community Standards or Terms of Service. However, the Abuse Team does not handle and will not respond to requests to remove content from the [SECOND_LIFE] world. +(1) The Abuse Process. You may submit an abuse report if you believe a Resident is exploiting the [SECOND_LIFE] permissions system, for example, by using CopyBot or similar copying tools, to infringe intellectual property rights. The Abuse Team investigates and issues appropriate disciplinary action for behavior that violates the [SECOND_LIFE] [http://secondlife.com/corporate/tos.php Terms of Service] or [http://secondlife.com/corporate/cs.php Community Standards]. However, the Abuse Team does not handle and will not respond to requests to remove content from the [SECOND_LIFE] world. -(2) The DMCA or Content Removal Process. To request removal of content from [SECOND_LIFE], you MUST submit a valid notification of infringement as provided in our DMCA Policy at http://secondlife.com/corporate/dmca.php. +(2) The DMCA or Content Removal Process. To request removal of content from [SECOND_LIFE], you MUST submit a valid notification of infringement as provided in our [http://secondlife.com/corporate/dmca.php DMCA Policy]. If you still wish to continue with the abuse process, please close this window and finish submitting your report. You may need to select the specific category 'CopyBot or Permissions Exploit'. @@ -5463,7 +5458,7 @@ Deactivated gestures with same trigger: name="NoQuickTime" type="notify"> Apple's QuickTime software does not appear to be installed on your system. -If you want to view streaming media on parcels that support it you should go to the QuickTime site (http://www.apple.com/quicktime) and install the QuickTime Player. +If you want to view streaming media on parcels that support it you should go to the [http://www.apple.com/quicktime QuickTime site] and install the QuickTime Player. </notification> <notification icon="notify.tga" @@ -5527,7 +5522,7 @@ The objects on the selected parcel that are NOT owned by you have been returned type="notify"> [MSG] </notification> - + <notification icon="notify.tga" name="NotSafe" @@ -5837,15 +5832,11 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a <button index="0" name="Keep" - text="OK"/> + text="Accept"/> <button index="1" name="Discard" - text="Cancel"/> - <button - index="2" - name="Mute" - text="Block"/> + text="No, thanks"/> </form> </notification> @@ -6153,7 +6144,7 @@ Thank you for your payment! Your L$ balance will be updated when processing completes. If processing takes more than 20 mins, your transaction may be cancelled. In that case, the purchase amount will be credited to your US$ balance. -The status of your payment can be checked on your Transaction History page at Me > My Dashboard, or http://secondlife.com/account/ +The status of your payment can be checked on your Transaction History page on your [http://secondlife.com/account/ Dashboard] </notification> <notification icon="notify.tga" @@ -6607,12 +6598,11 @@ Yes <global name="PermNo"> No </global> -<!-- this is alert string from server. the name needs to match entire the server string, and needs to be changed - whenever the server string changes --> +<!-- this is alert string from server. the name needs to match entire the server string, and needs to be changed + whenever the server string changes --> <global name="You can only set your 'Home Location' on your land or at a mainland Infohub."> -If you own a piece of land, you can make it your home location. +If you own a piece of land, you can make it your home location. Otherwise, you can look at the Map and find places marked "Infohub". - </global> - -</notifications> + </global> +</notifications> diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml index 4dc4a9ff46..8b815b0f71 100644 --- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml +++ b/indra/newview/skins/default/xui/en/panel_activeim_row.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel +<panel name="panel_activeim_row" layout="topleft" follows="left|right" @@ -7,56 +7,51 @@ left="0" height="35" width="318" - background_visible="true" - bevel_style="in" - bg_alpha_color="0 0 0 0"> + background_visible="false"> <chiclet_im_p2p name="p2p_chiclet" layout="topleft" follows="left" - top="5" + top="3" left="5" height="25" - width="45"> + width="25"> </chiclet_im_p2p> <chiclet_im_group name="group_chiclet" layout="topleft" follows="left" - top="5" + top="3" left="5" height="25" - width="45"> + width="25"> </chiclet_im_group> <text type="string" name="contact_name" layout="topleft" - top="8" - left_pad="6" - height="28" - width="235" + top="10" + left_pad="0" + height="14" + width="245" length="1" follows="right|left" - font="SansSerifBold" - text_color="White"> - Contact Name + use_ellipses="true" + font="SansSerifBold"> + Grumpity ProductEngine </text> <button - top="5" - left_pad="5" - width="15" - height="15" + top="10" + right="-5" + width="17" + height="17" layout="topleft" follows="right" name="hide_btn" mouse_opaque="true" label="" tab_stop="false" - image_unselected="toast_hide_btn.tga" - image_disabled="toast_hide_btn.tga" - image_selected="toast_hide_btn.tga" - image_hover_selected="toast_hide_btn.tga" - image_disabled_selected="toast_hide_btn.tga" + image_unselected="Toast_CloseBtn" + image_selected="Toast_CloseBtn" /> </panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index f747c557e2..18761c3bb9 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -39,7 +39,6 @@ <text follows="left|right" font="SansSerifSmall" - font.style="BOLD" height="15" layout="topleft" left_pad="5" @@ -47,17 +46,17 @@ top="6" use_ellipses="true" value="Unknown" - width="166" /> + width="182" /> <text - follows="left" + follows="right" font="SansSerifSmall" height="15" layout="topleft" - left_pad="10" - name="avatar_status" + left_pad="8" + name="last_interaction" text_color="LtGray_50" - value="Away" - width="50" /> + value="0s" + width="24" /> <output_monitor auto_update="true" follows="right" @@ -69,27 +68,26 @@ name="speaking_indicator" visible="true" width="20" /> - <button + <button follows="right" height="16" image_pressed="Info_Press" - image_hover="Info_Over" - image_unselected="Info_Off" + image_unselected="Info_Over" left_pad="3" - right="-25" + right="-31" name="info_btn" picture_style="true" + top_delta="-2" width="16" /> <button follows="right" - height="16" - image_selected="BuyArrow_Press" - image_pressed="BuyArrow_Press" - image_unselected="BuyArrow_Press" + height="20" + image_overlay="ForwardArrow_Off" layout="topleft" left_pad="5" - right="-5" + right="-3" name="profile_btn" picture_style="true" - width="16" /> + top_delta="-2" + width="20" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 9065c6b3e8..73a1bae1c6 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -10,6 +10,7 @@ left="0" name="bottom_tray" top="28" + chrome="true" border_visible="false" width="1000"> <layout_stack diff --git a/indra/newview/skins/default/xui/en/panel_chat_item.xml b/indra/newview/skins/default/xui/en/panel_chat_item.xml index 78f53562cd..05b04bbf8e 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_item.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_item.xml @@ -5,10 +5,10 @@ name="instant_message" width="300" height="180" - background_opaque="false" - background_visible="true" + background_opaque="true" + background_visible="false" follows="left|top|right|bottom" - bg_alpha_color="0.3 0.3 0.3 1.0"> + bg_alpha_color="0.3 0.3 0.3 0"> <panel width="250" height="30" background_visible="true" background_opaque="false" bg_alpha_color="0.0 0.0 0.0 1.0" name="msg_caption"> <avatar_icon top="25" left="10" width="20" height="20" follows="left|top" 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 b002034a08..fedc49ae87 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml @@ -136,6 +136,7 @@ layout="topleft" left="120" top="18" + max_length="512" name="sl_description_edit" width="173" word_wrap="true"> @@ -188,6 +189,7 @@ height="100" layout="topleft" left="120" + max_length="512" top="142" name="fl_description_edit" width="173" diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml index 9bd240eccc..a85c55f9b2 100644 --- a/indra/newview/skins/default/xui/en/panel_group_general.xml +++ b/indra/newview/skins/default/xui/en/panel_group_general.xml @@ -1,15 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel - border="true" follows="all" - height="445" + height="412" label="General" class="panel_group_general" layout="topleft" - left="1" + left="0" + top="0" name="general_tab" - top="500" - width="280"> + width="313"> <panel.string name="help_text"> The General tab contains general information about this group, a list of members, general Group Preferences and member options. @@ -18,7 +17,7 @@ Hover your mouse over the options for more help. </panel.string> <panel.string name="group_info_unchanged"> - General group information has changed. + General group information has changed </panel.string> <panel.string name="incomplete_member_data_str"> @@ -28,42 +27,28 @@ Hover your mouse over the options for more help. type="string" follows="left|top" left="5" - height="75" + height="60" layout="topleft" max_length="511" name="charter" top="5" - width="260" + width="303" word_wrap="true"> - Group Charter + Group Charter </text_editor> - <text - follows="left|top" - type="string" - font="SansSerifBig" - tool_tip="Owners are shown in bold." - height="16" - layout="topleft" - left="5" - name="text_owners_and_visible_members" - text_color="EmphasisColor" - top_pad="10" - width="270"> - Members - </text> <name_list column_padding="0" draw_heading="true" follows="left|top" - heading_height="14" - height="80" + heading_height="16" + height="160" layout="topleft" left_delta="0" name="visible_members" top_pad="0" - width="263"> + width="303"> <name_list.columns - label="Member Name" + label="Member" name="name" relative_width="0.6" /> <name_list.columns @@ -71,27 +56,16 @@ Hover your mouse over the options for more help. name="title" relative_width="0.4" /> </name_list> - <text - follows="left|top" - height="16" - type="string" - text_color="EmphasisColor" - top_pad="10" - font="SansSerifBig" - layout="topleft" - name="text_group_preferences"> - Group Preferences - </text> <text follows="left|top" type="string" - height="16" + height="14" layout="topleft" left_delta="0" name="active_title_label" - top_pad="8" - width="240"> - My Active Title + top_pad="5" + width="303"> + My Title </text> <combo_box follows="left|top" @@ -100,58 +74,58 @@ Hover your mouse over the options for more help. left_delta="0" name="active_title" tool_tip="Sets the title that appears in your avatar's name tag when this group is active." - top_pad="0" - width="240" /> + top_pad="2" + width="303" /> <check_box height="16" font="SansSerifSmall" label="Receive notices" layout="topleft" - left_delta="0" + left="5" name="receive_notices" tool_tip="Sets whether you want to receive Notices from this group. Uncheck this box if this group is spamming you." top_pad="5" - width="240" /> + width="303" /> <check_box height="16" label="Show in my profile" layout="topleft" - left_delta="0" + left="5" name="list_groups_in_profile" tool_tip="Sets whether you want to show this group in your profile" top_pad="5" - width="240" /> + width="303" /> <panel background_visible="true" bevel_style="in" border="true" bg_alpha_color="FloaterUnfocusBorderColor" follows="left|top" - height="125" + height="93" layout="topleft" - left_delta="0" + left="5" name="preferences_container" - top_pad="10" - width="263"> + top_pad="5" + width="303"> <check_box follows="right|top" height="16" label="Open enrollment" layout="topleft" - left_delta="0" + left="10" name="open_enrollement" tool_tip="Sets whether this group allows new members to join without being invited." top_pad="5" width="90" /> <check_box height="16" - label="Enrollment fee:" + label="Enrollment fee" layout="topleft" left_delta="0" name="check_enrollment_fee" tool_tip="Sets whether to require an enrollment fee to join the group" top_pad="5" - width="90" /> + width="300" /> <spinner decimal_digits="0" follows="left|top" @@ -161,43 +135,38 @@ Hover your mouse over the options for more help. label_width="20" label="L$" layout="topleft" - left="25" + right="-10" max_val="99999" - top_pad="5" + left_pad="2" name="spin_enrollment_fee" tool_tip="New members must pay this fee to join the group when Enrollment Fee is checked." - top_delta="-2" width="105" /> <check_box height="16" initial_value="true" label="Show in search" layout="topleft" - left="4" + left="10" name="show_in_group_list" tool_tip="Let people see this group in search results" top_pad="4" - width="90" /> + width="300" /> <combo_box height="20" layout="topleft" left_delta="0" name="group_mature_check" tool_tip="Sets whether your group information is considered mature" - top_pad="10" - width="240"> - <combo_box.item - label="- Select Mature -" - name="select_mature" - value="Select" /> - <combo_box.item - label="Mature Content" - name="mature" - value="Mature" /> + top_pad="5" + width="190"> <combo_box.item label="PG Content" name="pg" value="Not Mature" /> - </combo_box> + <combo_box.item + label="Mature Content" + name="mature" + value="Mature" /> + </combo_box> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml index da6cf8891a..d8d47c4008 100644 --- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml @@ -1,20 +1,22 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> - <panel - follows="left|top|right|bottom" - height="660" - label="Group Info" - layout="topleft" - name="panel_group_info" - border="false" - width="300"> +background_visible="true" + follows="all" + height="570" + label="Group Info" + layout="topleft" + min_height="350" + left="0" + top="20" + name="GroupInfo" + width="333"> <panel.string name="default_needs_apply_text"> - There are unapplied changes on the current tab. + There are unsaved changes to the current tab </panel.string> <panel.string name="want_apply_text"> - Do you want to apply these changes? + Do you want to save these changes? </panel.string> <panel.string name="group_join_btn"> @@ -25,34 +27,34 @@ Free </panel.string> <button - layout="topleft" - name="back" - right="-9" - top="0" - width="25" - height="25" - label="" follows="top|right" + height="23" image_overlay="BackArrow_Off" - tab_stop="false" /> - <text layout="topleft" - top="0" + name="back" + picture_style="true" left="10" - width="250" - height="20" + tab_stop="false" + top="2" + width="23" /> + <text + follows="top|left|right" font="SansSerifHugeBold" + height="26" + layout="topleft" + left_pad="10" + name="group_name" text_color="white" - follows="top|left|right" - mouse_opaque="true" - use_ellipses="true" - name="group_name">(Loading...)</text> + top="0" + value="(Loading...)" + use_elipsis="true" + width="300" /> <line_editor follows="left|top" font="SansSerif" label="Type your new group name here" layout="topleft" - left_delta="0" + left_delta="10" max_length="35" name="group_name_editor" top_delta="5" @@ -64,7 +66,7 @@ height="113" label="" layout="topleft" - left="10" + left="20" name="insignia" tool_tip="Click to choose a picture" top_pad="5" @@ -79,7 +81,7 @@ name="prepend_founded_by" top_delta="0" width="140"> - Founded by: + Founder: </text> <name_box follows="left|top" @@ -88,10 +90,12 @@ layout="topleft" left_delta="0" name="founder_name" - top_pad="10" + top_pad="2" use_ellipses="true" width="140" /> <text + font="SansSerifBig" + text_color="EmphasisColor" type="string" follows="left|top" height="16" @@ -106,22 +110,84 @@ <button follows="left|top" left_delta="0" - top_pad="10" - height="20" + top_pad="6" + height="23" label="Join now!" label_selected="Join now!" name="btn_join" visible="true" - width="85" /> - <button - top="632" - height="20" - font="SansSerifSmall" - label="Save" - label_selected="Save" - name="btn_apply" - left="5" - width="65" /> + width="120" /> + <accordion + follows="all" + height="405" + layout="topleft" + left="0" + name="groups_accordion" + top_pad="20" + width="333"> + <accordion_tab + can_resize="false" + layout="topleft" + name="tab_general" + title="General"> + <panel + border="false" + filename="panel_group_general.xml" + layout="topleft" + left="0" + help_topic="group_general_tab" + name="general_tab" + top="0" + width="333" /> + </accordion_tab> + <accordion_tab + can_resize="false" + expanded="false" + layout="topleft" + name="tab_roles" + title="Roles"> + <panel + border="false" + filename="panel_group_roles.xml" + layout="topleft" + left="0" + help_topic="group_roles_tab" + name="roles_tab" + top="0" + width="333" /> + </accordion_tab> + <accordion_tab + can_resize="false" + expanded="false" + layout="topleft" + name="tab_notices" + title="Notices"> + <panel + filename="panel_group_notices.xml" + layout="topleft" + left="0" + help_topic="group_notices_tab" + name="notices_tab" + top="0" + width="333" /> + </accordion_tab> + <accordion_tab + can_resize="false" + expanded="false" + layout="topleft" + name="tab_notices" + title="Land/Assets"> + <panel + border="false" + filename="panel_group_land_money.xml" + layout="topleft" + left="0" + help_topic="group_land_money_tab" + name="land_money_tab" + top="0" + width="333" /> + </accordion_tab> + </accordion> <button follows="top|left" height="20" @@ -129,41 +195,31 @@ layout="topleft" name="btn_refresh" picture_style="true" - top="632" - left="75" + left="5" width="20" /> + <button + height="20" + font="SansSerifSmall" + label="Save" + label_selected="Save" + name="btn_apply" + left_pad="5" + width="65" /> <button - top="632" height="20" label="Create" label_selected="Create" name="btn_create" - left="5" + left_pad="5" visible="false" width="65" /> <button - top="632" - left="75" + left_pad="5" height="20" label="Cancel" label_selected="Cancel" name="btn_cancel" visible="false" width="65" /> - <accordion layout="topleft" left="2" width="296" top="135" height="500" follows="all" name="group_accordion"> - <accordion_tab min_height="445" title="General" name="group_general_tab"> - <panel class="panel_group_general" filename="panel_group_general.xml" name="group_general_tab_panel"/> - </accordion_tab> - <accordion_tab min_height="380" title="Members & Roles" name="group_roles_tab" expanded="False" can_resize="false"> - <panel class="panel_group_roles" filename="panel_group_roles.xml" name="group_roles_tab_panel"/> - </accordion_tab> - <accordion_tab min_height="530" title="Notices" name="group_notices_tab" expanded="False" can_resize="false"> - <panel class="panel_group_notices" filename="panel_group_notices.xml" name="group_notices_tab_panel"/> - </accordion_tab> - <accordion_tab min_height="270" title="Land & L$" name="group_land_tab" expanded="False" can_resize="false"> - <panel class="panel_group_land_money" filename="panel_group_land_money.xml" name="group_land_tab_panel"/> - </accordion_tab> - </accordion> - </panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml index 0845ec014e..04e0ad3be8 100644 --- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml @@ -230,7 +230,7 @@ top_delta="0" width="250"> Group members must contribute more land credits to support land in use. - </text> + </text> <text type="string" follows="left|top" @@ -247,15 +247,17 @@ <tab_container follows="all" height="200" + halign="center" layout="topleft" left="10" name="group_money_tab_container" tab_position="top" + tab_height="20" top_pad="10" width="265"> <panel border="true" - follows="left|top|right|bottom" + follows="all" height="180" label="Planning" layout="topleft" @@ -305,7 +307,7 @@ width="250" word_wrap="true"> Computing... - </text_editor> + </text_editor> <button height="20" label="< Earlier" @@ -325,7 +327,7 @@ name="later_details_button" tool_tip="Go forward in time" top_delta="0" - width="125" /> + width="125" /> </panel> <panel border="true" @@ -375,4 +377,4 @@ width="125" /> </panel> </tab_container> -</panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item.xml b/indra/newview/skins/default/xui/en/panel_group_list_item.xml index 7bdcaafe31..ffa485051c 100644 --- a/indra/newview/skins/default/xui/en/panel_group_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_group_list_item.xml @@ -28,13 +28,11 @@ visible="false" width="320" /> <icon - follows="top|left" height="20" image_name="Generic_Group" name="group_icon" - layout="topleft" - left="5" mouse_opaque="true" + left="5" top="2" width="20" /> <text @@ -47,28 +45,28 @@ top="6" use_ellipses="true" value="Unknown" - width="246" /> + width="242" /> <button follows="right" height="16" image_pressed="Info_Press" - image_hover="Info_Over" - image_unselected="Info_Off" + image_unselected="Info_Over" left_pad="3" - right="-25" + right="-31" name="info_btn" picture_style="true" + top_delta="-2" width="16" /> + <!--*TODO: Should only appear on rollover--> <button follows="right" - height="16" - image_selected="BuyArrow_Press" - image_pressed="BuyArrow_Press" - image_unselected="BuyArrow_Press" + height="20" + image_overlay="ForwardArrow_Off" layout="topleft" left_pad="5" - right="-5" + right="-3" name="profile_btn" picture_style="true" - width="16" /> + top_delta="-2" + width="20" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml index af1919bd8f..909c3f4577 100644 --- a/indra/newview/skins/default/xui/en/panel_group_roles.xml +++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml @@ -1,20 +1,20 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel - border="true" - height="490" + border="false" + height="412" label="Members & Roles" layout="topleft" - left="1" + left="0" + top="0" name="roles_tab" - top="490" - width="280"> + width="313"> <panel.string name="default_needs_apply_text"> - There are unapplied changes on the current sub-tab. + There are unsaved changes to the current tab </panel.string> <panel.string name="want_apply_text"> - Do you want to apply these changes? + Do you want to save these changes? </panel.string> <panel.string name="help_text" /> @@ -160,17 +160,20 @@ </text> </panel> --> <tab_container + border="true" follows="left|top" - height="180" + height="260" + halign="center" layout="topleft" left="5" name="roles_tab_container" tab_position="top" - top="10" - width="265"> + tab_height="20" + top="0" + width="303"> <panel - border="true" - height="165" + border="false" + height="260" label="Members" layout="topleft" left="1" @@ -179,7 +182,7 @@ tool_tip="Members" top="17" class="panel_group_members_subtab" - width="265"> + width="300"> <panel.string name="help_text"> You can add or remove Roles assigned to Members. @@ -190,77 +193,56 @@ clicking on their names. layout="topleft" top="10" left="4" - width="255" + width="280" height="20" follows="left|top|right" max_length="250" label="Filter Members" name="filter_input" font="SansSerif" /> - <!--<line_editor - border_style="line" - border_thickness="1" - follows="left|top" - height="16" - layout="topleft" - left="4" - max_length="63" - name="search_text" - top="10" - width="90" /> - <button - font="SansSerifSmall" - height="20" - label="Search" - layout="topleft" - left_pad="5" - name="search_button" - top_delta="-2" - width="80" /> - <button + <!-- <button enabled="false" font="SansSerifSmall" height="20" label="Show All" layout="topleft" - left_pad="0" + left_pad="-90" name="show_all_button" - top_delta="0" - width="80" /> --> + top_delta="-6" + width="80" />--> <name_list column_padding="0" draw_heading="true" - heading_height="14" - height="100" + heading_height="20" + height="160" follows="left|top" layout="topleft" - left="4" + left="0" multi_select="true" name="member_list" - top_pad="6" - width="255"> + top_pad="2" + width="300"> <name_list.columns label="Member" name="name" - width="90" /> + relative_width="0.45" /> <name_list.columns label="Donations" name="donated" - width="95" /> + relative_width="0.3" /> <name_list.columns label="Online" name="online" - width="80" /> + relative_width="0.2" /> </name_list> <button height="20" font="SansSerifSmall" label="Invite" layout="topleft" - left_delta="0" name="member_invite" - top_pad="6" - width="125" /> + top_pad="3" + width="100" /> <button height="20" font="SansSerifSmall" @@ -268,18 +250,17 @@ clicking on their names. layout="topleft" left_pad="5" name="member_eject" - top_delta="0" - width="125" /> + width="100" /> <icon height="16" - image_name="inv_folder_plain_closed.tga" + image_name="Inv_FolderClosed" layout="topleft" name="power_folder_icon" visible="false" width="16" /> </panel> <panel - border="true" + border="false" height="164" label="Roles" layout="topleft" @@ -292,7 +273,7 @@ clicking on their names. <panel.string name="help_text"> Roles have a title and an allowed list of Abilities -that Members can perform. Members can belong to +that Members can perform. Members can belong to one or more Roles. A group can have up to 10 Roles, including the Everyone and Owner Roles. </panel.string> @@ -302,7 +283,7 @@ including the Everyone and Owner Roles. </panel.string> <panel.string name="power_folder_icon"> - inv_folder_plain_closed.tga + Inv_FolderClosed </panel.string> <panel.string name="power_all_have_icon"> @@ -316,7 +297,7 @@ including the Everyone and Owner Roles. layout="topleft" top="10" left="4" - width="255" + width="260" height="20" follows="left|top|right" max_length="250" @@ -357,13 +338,13 @@ including the Everyone and Owner Roles. column_padding="0" draw_heading="true" follows="left|top" - heading_height="14" - height="100" + heading_height="20" + height="150" layout="topleft" left="4" name="role_list" top_pad="4" - width="255"> + width="300"> <scroll_list.columns label="Role" name="name" @@ -397,7 +378,7 @@ including the Everyone and Owner Roles. width="125" /> </panel> <panel - border="true" + border="false" height="164" label="Abilities" layout="topleft" @@ -407,7 +388,7 @@ including the Everyone and Owner Roles. class="panel_group_actions_subtab" top="17" tool_tip="You can view an Ability's Description and which Roles and Members can execute the Ability." - width="265"> + width="300"> <panel.string name="help_text"> Abilities allow Members in Roles to do specific @@ -486,13 +467,13 @@ things in this group. There's a broad variety of Abilities. </panel> </tab_container> <panel - height="190" + height="150" layout="topleft" follows="left|top" left="10" name="members_footer" - top_pad="10" - width="265"> + top_pad="2" + width="300"> <text type="string" font="SansSerif" diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml index 00ede1fb2c..26d8304551 100644 --- a/indra/newview/skins/default/xui/en/panel_instant_message.xml +++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml @@ -1,15 +1,14 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel background_visible="true" - bevel_style="in" bg_alpha_color="0.3 0.3 0.3 0" - height="140" + height="175" label="im_panel" layout="topleft" left="0" name="im_panel" top="0" - width="350"> + width="305"> <string name="message_max_lines_count"> 6 @@ -19,50 +18,52 @@ bevel_style="in" bg_alpha_color="black" follows="top" - height="30" + height="20" label="im_header" layout="topleft" left="5" name="im_header" top="5" - width="340"> + width="295"> <avatar_icon follows="right" height="20" image_name="icon_avatar_online.tga" layout="topleft" - left="5" + left="0" mouse_opaque="true" name="avatar_icon" - top="5" + top="0" width="20" /> <icon follows="right" height="20" image_name="icon_top_pick.tga" layout="topleft" - left="5" + left="0" mouse_opaque="true" name="sys_msg_icon" - top="5" + top="0" width="20" /> <text follows="left|right" - font="SansSerifBigBold" + font="SansSerifBold" height="20" layout="topleft" - left_pad="10" + left_pad="5" name="user_name" text_color="white" top="5" value="Darth Vader" - width="250" /> + width="295" /> + <!-- TIME STAMP --> <text follows="right" - font="SansSerifBig" + font="SansSerif" height="20" layout="topleft" - left_pad="10" + halign="right" + left="245" name="time_box" text_color="white" top="5" @@ -71,25 +72,25 @@ </panel> <text follows="left|top|bottom|right" - height="60" + height="86" layout="topleft" left="10" name="message" text_color="white" - top="40" + top="33" use_ellipses="true" value="MESSAGE" - width="330" + width="285" word_wrap="true" max_length="350" /> <button follows="bottom" - font="SansSerifBigBold" + font="SansSerifBold" height="25" - label="reply" + label="Reply" layout="topleft" - left="120" + left="97" name="reply" - top="110" + top="137" width="110" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index 8cebabdcda..b6218ad932 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -26,33 +26,31 @@ width="300" />
<tab_container
follows="left|top|right|bottom"
- height="320"
+ height="508"
layout="topleft"
left_delta="-4"
name="inventory filter tabs"
tab_position="top"
top_pad="4"
- width="313">
+ width="463">
<inventory_panel
follows="left|top|right|bottom"
- border="true"
- height="310"
+ height="491"
label="All Items"
layout="topleft"
- left="10"
+ left="1"
name="All Items"
top="16"
- width="250" />
+ width="461" />
<inventory_panel
follows="left|top|right|bottom"
- border="true"
- height="310"
+ height="491"
label="Recent Items"
layout="topleft"
left_delta="0"
name="Recent Items"
top_delta="0"
- width="250" />
+ width="461" />
</tab_container>
<menu_bar
bg_visible="false"
@@ -154,7 +152,7 @@ layout="topleft"
name="Reset Current">
<menu_item_call.on_click
- function="Inventory.ResetFilters" />
+ function="Inventory.ResetFilter" />
</menu_item_call>
<menu_item_call
label="Close All Folders"
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 af00b96d27..2182163da5 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 @@ -23,6 +23,7 @@ layout="topleft" left_delta="7" left="0" + max_length="254" name="chat_box" tool_tip="Press Enter to say, Ctrl+Enter to shout" top="0" diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml index 9c2829d92d..0d34aa0f08 100644 --- a/indra/newview/skins/default/xui/en/panel_notification.xml +++ b/indra/newview/skins/default/xui/en/panel_notification.xml @@ -1,37 +1,51 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel - background_opaque="true" - background_visible="false" + background_opaque="false" + border_visible="false" + border = "false" + border_drop_shadow_visible = "false" + drop_shadow_visible = "false" + background_visible="true" bg_alpha_color="0.3 0.3 0.3 0" - height="140" + bg_opaque_color="0.3 0.3 0.3 0" label="notification_panel" layout="topleft" left="0" name="notification_panel" top="0" - width="350"> + height="10" + width="305"> + <!-- THIS PANEL CONTROLS TOAST HEIGHT? --> <panel + border_visible="false" + drop_shadow="false" + bevel_style="none" + border_style="none" + border = "false" + border_drop_shadow_visible = "false" + drop_shadow_visible = "false" background_visible="true" - bg_alpha_color="0.3 0.3 0.3 0" + bg_alpha_color="0.3 0.3 0.3 0" + bg_opaque_color="0.3 0.3 0.3 0" follows="left|right|top" - height="100" + height="10" label="info_panel" layout="topleft" left="0" name="info_panel" top="0" - width="350"> - <text + width="305"> + <!-- <text border_visible="false" follows="left|right|top|bottom" font="SansSerif" height="90" layout="topleft" - left="45" + left="10" name="text_box" read_only="true" text_color="white" - top="5" + top="10" visible="false" width="300" wrap="true"/> @@ -47,40 +61,43 @@ top="5" visible="false" width="300" - wrap="true"/> + wrap="true"/> --> <text_editor + h_pad="0" + v_pad="0" bg_readonly_color="0.0 0.0 0.0 0" border_visible="false" + border = "false" + border_drop_shadow_visible = "false" + drop_shadow_visible = "false" embedded_items="false" enabled="false" follows="left|right|top|bottom" font="SansSerif" - height="90" layout="topleft" - left="45" + left="10" mouse_opaque="false" name="text_editor_box" read_only="true" tab_stop="false" text_color="white" text_readonly_color="white" - top="5" + top="10" visible="false" - width="300" + width="285" wrap="true"/> </panel> <panel - background_visible="true" - bg_alpha_color="0.3 0.3 0.3 0" + background_visible="false" follows="left|right|bottom" - height="40" label="control_panel" layout="topleft" left="0" + left_delta="-38" name="control_panel" - top_pad="0" - width="350"> + top="20"> </panel> + <!-- <icon follows="left|top" height="32" @@ -90,5 +107,5 @@ mouse_opaque="false" name="info_icon" top="20" - width="32" /> + width="32" /> --> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 69089e0e26..e234a7b358 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -34,7 +34,6 @@ background_visible="true" value="Filter Groups" /> <filter_editor follows="left|top|right" - font="SansSerif" height="23" layout="topleft" left="15" @@ -49,18 +48,17 @@ background_visible="true" height="500" layout="topleft" left="10" - font="SansSerifBigBold" name="tabs" tab_min_width="70" tab_height="30" tab_position="top" top_pad="10" - halign="center" + halign="center" width="313"> <panel follows="all" height="500" - label="Nearby" + label="NEARBY" layout="topleft" left="0" help_topic="people_nearby_tab" @@ -100,17 +98,30 @@ background_visible="true" picture_style="true" top="5" width="18" /> + <button + follows="bottom|left" + height="18" + image_selected="AddItem_Press" + image_unselected="AddItem_Off" + image_disabled="AddItem_Disabled" + layout="topleft" + left_pad="5" + name="add_friend_btn" + picture_style="true" + top_delta="0" + tool_tip="Add selected resident to your friends List" + width="18" /> </panel> </panel> <panel follows="all" height="500" - left="0" - top="0" - label="Friends" + label="FRIENDS" layout="topleft" + left="0" help_topic="people_friends_tab" name="friends_panel" + top="0" width="313"> <accordion follows="all" @@ -123,14 +134,13 @@ background_visible="true" <accordion_tab can_resize="false" layout="topleft" - height="230" + height="235" min_height="150" name="tab_online" title="Online"> <avatar_list allow_select="true" follows="all" - height="150" layout="topleft" left="0" multi_select="true" @@ -141,13 +151,12 @@ background_visible="true" <accordion_tab can_resize="false" layout="topleft" - height="230" + height="235" name="tab_all" title="All"> <avatar_list allow_select="true" follows="all" - height="230" layout="topleft" left="0" multi_select="true" @@ -209,11 +218,12 @@ background_visible="true" <panel follows="all" height="500" - label="Groups" - top="0" + label="GROUPS" layout="topleft" + left="0" help_topic="people_groups_tab" name="groups_panel" + top="0" width="313"> <group_list follows="all" @@ -287,13 +297,14 @@ background_visible="true" </panel> </panel> <panel - top="0" follows="all" height="500" - label="Recent" + label="RECENT" layout="topleft" + left="0" help_topic="people_recent_tab" name="recent_panel" + top="0" width="313"> <avatar_list allow_select="true" @@ -303,11 +314,10 @@ background_visible="true" left="0" multi_select="true" name="avatar_list" - top="2" + show_last_interaction_time="true" + top="0" width="313" /> <panel - background_visible="true" - bevel_style="none" top_pad="0" follows="left|right|bottom" height="30" @@ -329,6 +339,19 @@ background_visible="true" picture_style="true" top="7" width="18" /> + <button + follows="bottom|left" + height="18" + image_selected="AddItem_Press" + image_unselected="AddItem_Off" + image_disabled="AddItem_Disabled" + layout="topleft" + left_pad="5" + name="add_friend_btn" + picture_style="true" + top_delta="0" + tool_tip="Add selected resident to your friends List" + width="18" /> </panel> </panel> </tab_container> @@ -344,104 +367,88 @@ background_visible="true" width="313"> <layout_panel default_tab_group="1" - follows="left|top|right" + follows="left|top" height="25" layout="topleft" left="0" name="view_profile_btn_panel" top="-25" - width="65"> + width="100"> <button - follows="top|left|right" + follows="top|left" font="SansSerifSmall" height="19" label="Profile" layout="topleft" name="view_profile_btn" tool_tip="Show picture, groups, and other residents information" - width="65" /> - </layout_panel> - <layout_panel - default_tab_group="1" - follows="left|top|right" - height="25" - layout="topleft" - left_delta="0" - min_width="85" - name="add_friend_btn_panel" - top_delta="0" - width="50"> - <button - follows="top|left|right" - font="SansSerifSmall" - height="19" - label="Add" - layout="topleft" - name="add_friend_btn" - tool_tip="Add selected resident to your friends List" - width="50" /> + width="100" /> </layout_panel> <layout_panel default_tab_group="1" - follows="left|top|right" + follows="left|top" height="19" layout="topleft" + left="0" min_width="80" name="group_info_btn_panel" - width="80"> + width="100"> <button - follows="top|left|right" + follows="top|left" font="SansSerifSmall" height="19" label="Group Profile" layout="topleft" name="group_info_btn" tool_tip="Show group information" - width="80" /> + width="100" /> </layout_panel> <layout_panel default_tab_group="1" - follows="left|top|right" + follows="left|top" height="25" layout="topleft" + left_pad="5" min_width="45" name="chat_btn_panel" top_delta="0" - width="45"> + width="100"> <button - follows="top|left|right" + follows="top|left" font="SansSerifSmall" height="19" - label="Chat" + label="Group Chat" layout="topleft" name="chat_btn" tool_tip="Open chat session" - width="45" /> + width="100" /> </layout_panel> <layout_panel default_tab_group="1" - follows="left|top|right" + follows="left|top|" height="25" layout="topleft" + left_pad="5" min_width="35" name="im_btn_panel" top_delta="0" - width="35"> + width="50"> <button - follows="top|left|right" + follows="top|left" font="SansSerifSmall" height="19" label="IM" layout="topleft" name="im_btn" tool_tip="Open instant message session" - width="35" /> + width="50" /> </layout_panel> <layout_panel default_tab_group="1" follows="left|top|right" height="25" layout="topleft" + left_pad="5" min_width="40" name="call_btn_panel" top_delta="0" @@ -449,53 +456,55 @@ background_visible="true" width="40"> <button enabled="false" - follows="top|left|right" + follows="top|left" font="SansSerifSmall" height="19" label="Call" layout="topleft" name="call_btn" - width="40" /> + width="50" /> </layout_panel> <layout_panel default_tab_group="1" - follows="left|top|right" + follows="left|top" height="25" layout="topleft" + left_pad="5" min_width="65" name="teleport_btn_panel" top_delta="0" - width="65"> + width="100"> <button - follows="left|top|right" + follows="left|top" font="SansSerifSmall" height="19" label="Teleport" layout="topleft" name="teleport_btn" tool_tip="Offer teleport" - width="65" /> + width="100" /> </layout_panel> <layout_panel default_tab_group="1" enabled="false" - follows="left|top|right" + follows="left|top" height="25" layout="topleft" + left_pad="5" min_width="50" name="share_btn_panel" top_delta="0" visible="false" - width="50"> + width="80"> <button enabled="false" - follows="top|left|right" + follows="top|left" font="SansSerifSmall" height="19" label="Share" layout="topleft" name="share_btn" - width="50" /> + width="80" /> </layout_panel> </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml index 1074dd4627..38ea6b6196 100644 --- a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml @@ -57,7 +57,7 @@ use_ellipses="false" width="197" word_wrap="false" /> - <text + <expandable_text follows="top|left|right" font="SansSerifSmall" height="40" diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index 50108aa21f..5aa53ab46b 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -12,10 +12,10 @@ background_visible="true" width="333"> <string name="landmarks_tab_title" - value="My Landmarks" /> + value="MY LANDMARKS" /> <string name="teleport_history_tab_title" - value="Teleport History" /> + value="TELEPORT HISTORY" /> <filter_editor follows="left|top|right" font="SansSerif" @@ -29,11 +29,12 @@ background_visible="true" width="303" /> <tab_container follows="all" + halign="center" height="500" layout="topleft" left="10" name="Places Tabs" - tab_min_width="70" + tab_min_width="80" tab_height="30" tab_position="top" top_pad="10" 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 f42bab14de..91dcdce23b 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -20,8 +20,9 @@ </panel.string> <check_box control_name="UseChatBubbles" + follows="left|top" height="16" - label="Bubble Chat" + label="Bubble chat" layout="topleft" left="30" top="10" @@ -30,6 +31,7 @@ <slider control_name="ChatBubbleOpacity" + follows="left|top" height="16" increment="0.05" initial_value="1" @@ -40,40 +42,24 @@ label_width="50" name="bubble_chat_opacity" width="200" /> - - <!-- <check_box - control_name="UIAutoScale" - height="16" - label="Resolution independent scale" - layout="topleft" - left="30" - name="ui_auto_scale" - top_pad="10" - width="256" />--> - <!-- - <combo_box - height="18" - layout="topleft" - left_pad="5" - name="fullscreen combo" - top_delta="-1" - width="150" /--> <text + follows="left|top" type="string" length="1" height="25" layout="topleft" left="30" - top_pad="20" + top_pad="5" name="AspectRatioLabel1" tool_tip="width / height" label_width="50" width="120"> - Aspect Ratio + Aspect ratio </text> <combo_box allow_text_entry="true" height="20" + follows="left|top" layout="topleft" left_pad="0" max_chars="100" @@ -104,6 +90,7 @@ </combo_box> <check_box control_name="FullScreenAutoDetectAspectRatio" + follows="left|top" height="25" label="Auto-detect" layout="topleft" @@ -113,14 +100,14 @@ <check_box.commit_callback function="Pref.AutoDetectAspect" /> </check_box> - <text + follows="left|top" type="string" length="1" height="10" left="30" name="heading1" - top_pad="10" + top_pad="5" width="270"> Camera: </text> @@ -128,7 +115,7 @@ Camera: can_edit_text="true" control_name="CameraAngle" decimal_digits="2" - top_pad="10" + top_pad="5" follows="left|top" height="16" increment="0.025" @@ -159,56 +146,62 @@ Camera: name="camera_offset_scale" show_text="false" width="240" - top_pad="10"/> + top_pad="5"/> <text + follows="left|top" type="string" length="1" height="10" left="30" name="heading2" - width="270"> + width="270" + top_pad="5"> Automatic positioning for: </text> <check_box control_name="EditCameraMovement" height="20" + follows="left|top" label="Build/Edit" layout="topleft" left_delta="50" name="edit_camera_movement" tool_tip="Use automatic camera positioning when entering and exiting edit mode" width="280" - top_pad="10" /> + top_pad="5" /> <check_box control_name="AppearanceCameraMovement" + follows="left|top" height="16" label="Appearance" layout="topleft" name="appearance_camera_movement" tool_tip="Use automatic camera positioning while in edit mode" width="242" /> - <text + follows="left|top" type="string" length="1" height="10" left="30" name="heading3" - top_pad="10" + top_pad="5" width="270"> Avatars: </text> <check_box control_name="FirstPersonAvatarVisible" + follows="left|top" height="20" label="Show me in Mouselook" layout="topleft" left_delta="50" name="first_person_avatar_visible" width="256" - top_pad="10"/> + top_pad="0"/> <check_box control_name="ArrowKeysMoveAvatar" + follows="left|top" height="20" label="Arrow keys always move me" layout="topleft" @@ -218,6 +211,7 @@ Avatars: top_pad="0"/> <check_box control_name="AllowTapTapHoldRun" + follows="left|top" height="20" label="Tap-tap-hold to run" layout="topleft" @@ -227,6 +221,7 @@ Avatars: top_pad="0"/> <check_box control_name="LipSyncEnabled" + follows="left|top" height="20" label="Move avatar lips when speaking" layout="topleft" @@ -236,16 +231,18 @@ Avatars: top_pad="0" /> <check_box control_name="ShowScriptErrors" + follows="left|top" height="20" label="Show script errors" layout="topleft" left="30" name="show_script_errors" width="256" - top_pad="10"/> + top_pad="5"/> <radio_group enabled_control="ShowScriptErrors" control_name="ShowScriptErrorsLocation" + follows="top|left" draw_border="false" height="40" layout="topleft" @@ -259,17 +256,53 @@ Avatars: layout="topleft" left="3" name="0" - top="3" + top="0" width="315" /> <radio_item height="16" label="In window" layout="topleft" - left_delta="0" + left_delta="175" name="1" - top_delta="16" + top_delta="0" width="315" /> </radio_group> - - + <check_box + follows="top|left" + height="20" + label="Use Push-to-talk in toggle mode" + layout="topleft" + left="30" + name="push_to_talk_toggle_check" + width="237" + top_pad="-25" + tool_tip="When in toggle mode, press and release the push-to-talk trigger to switch your microphone on and off. When not in toggle mode, the microphone is active only when the trigger is held down."/> + <line_editor + follows="top|left" + height="19" + left_delta="50" + max_length="254" + name="modifier_combo" + label="Push-to-talk trigger" + top_pad="0" + width="280" /> + <button + follows="top|left" + height="20" + label="Set Key" + left_delta="0" + name="set_voice_hotkey_button" + width="115" + top_pad="5" /> + <button + bottom_delta="0" + follows="left" + font="SansSerif" + halign="center" + height="20" + label="Middle Mouse Button" + left_delta="120" + mouse_opaque="true" + name="set_voice_middlemouse_button" + width="160" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index 73a759a8ba..5af7d7d674 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -81,6 +81,7 @@ height="95" layout="topleft" left="107" + max_length="512" name="sl_description_edit" top_pad="-3" width="173" @@ -123,6 +124,7 @@ height="95" layout="topleft" left="107" + max_length="512" name="fl_description_edit" top_pad="-3" width="173" diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml index 7a5781651d..195b731531 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_view.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml @@ -50,6 +50,7 @@ <tab_container follows="all" height="535" + halign="center" layout="topleft" left="10" min_width="333" 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 795e0ffc0d..7b9c9f47a2 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -41,20 +41,18 @@ </panel.string> <button auto_resize="true" - halign="right" + halign="right" follows="right|bottom" font="SansSerifSmall" - image_color="White_05" - flash_color="EmphasisColor" - image_overlay="BuyArrow_Over" - height="18" - layout="topleft" - left="-225" + image_selected="BuyArrow_Over" + image_unselected="BuyArrow_Off" + image_pressed="BuyArrow_Press" + height="16" + left="-220" name="buycurrency" - pad_right="23px" - picture_style="true" + pad_right="22px" tool_tip="My Balance: Click to buy more L$" - top="0" + top="1" width="117" /> <text type="string" @@ -65,148 +63,21 @@ height="16" top="3" layout="topleft" - left_pad="20" + left_pad="15" name="TimeText" text_color="TimeTextColor" tool_tip="Current time (Pacific)" width="80"> 12:00 AM </text> - <button - follows="right|bottom" - height="16" - layout="topleft" - left_delta="-537" - image_selected="Inv_DangerousScript" - image_unselected="Inv_DangerousScript" - name="scriptout" - picture_style="true" - scale_image="false" - tool_tip="Script warnings and errors" - top="0" - visible="false" - width="16" /> - <button - follows="right|bottom" - height="16" - image_selected="Health" - image_unselected="Health" - layout="topleft" - left_pad="7" - name="health" - picture_style="true" - scale_image="false" - tool_tip="Health" - top="0" - visible="false" - width="16" /> - <text - bg_visible="false" - text_readonly_color="HealthTextColor" - follows="rsight|bottom" - font_shadow="none" - height="16" - layout="topleft" - left_pad="18" - name="HealthText" - text_color="HealthTextColor" - tool_tip="Health" - top="0" - visible="false" - width="31"> - 100% - </text> - <button - follows="right|bottom" - height="16" - image_selected="Move_Fly_Disabled" - image_unselected="Move_Fly_Disabled" - layout="topleft" - left_pad="7" - name="no_fly" - picture_style="true" - scale_image="false" - tool_tip="Flying not allowed" - top="3" - visible="false" - width="16" /> - <button - follows="right|bottom" - height="16" - image_selected="Tool_Create" - image_unselected="Tool_Create" - layout="topleft" - left_pad="7" - name="no_build" - picture_style="true" - scale_image="false" - tool_tip="Building/rezzing not allowed" - top="0" - visible="false" - width="16" /> - <button - follows="right|bottom" - height="16" - image_selected="Inv_Script" - image_unselected="Inv_Script" - layout="topleft" - left_pad="7" - name="no_scripts" - picture_style="true" - scale_image="false" - tool_tip="Scripts not allowed" - top="0" - visible="false" - width="16" /> - <button - follows="right|bottom" - height="16" - image_selected="Inv_Gesture" - image_unselected="Inv_Gesture" - layout="topleft" - left_pad="7" - name="restrictpush" - picture_style="true" - scale_image="false" - tool_tip="No pushing" - top="0" - visible="false" - width="16" /> - <button - follows="right|bottom" - height="18" - image_selected="Microphone_Mute" - image_unselected="Microphone_Mute" - layout="topleft" - left_pad="7" - name="status_no_voice" - picture_style="true" - scale_image="false" - tool_tip="Voice not available here" - top="1" - visible="false" - width="16" /> - <button - follows="right|bottom" - height="16" - image_selected="Icon_For_Sale" - image_unselected="Icon_For_Sale" - layout="topleft" - left_pad="7" - name="buyland" - picture_style="true" - tool_tip="Buy this parcel" - top="0" - visible="false" - width="16" /> <text enabled="true" follows="right|bottom" halign="center" height="12" layout="topleft" - left_delta="-4" + left_delta="0" name="stat_btn" - top_delta="3" - width="20" /> + top_delta="0" + width="20"/> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml index 53ee0d159d..7722583ce2 100644 --- a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml +++ b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml @@ -1,65 +1,40 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <!-- All our XML is utf-8 encoded. --> - <panel - name="sys_well_item" - title="sys_well_item" + name="sys_well_item" + title="sys_well_item" visible="true" - top="0" - left="0" - width="318" - height="35" + top="0" + left="0" + width="300" + height="35" layout="topleft" - follows="left|right" - background_opaque="false" - background_visible="true" - bg_alpha_color="0.0 0.0 0.0 0.0" > - - <icon - top="8" - left="8" - width="20" - height="20" - layout="topleft" - follows="left" - name="icon" - label="" - mouse_opaque="false" - image_name="lag_status_warning.tga" - /> - + follows="left|right"> <text - top="2" - left_pad="8" - width="255" - height="28" + top="2" + left="10" + width="267" + height="28" layout="topleft" follows="right|left" - font="SansSerifBold" text_color="white" - use_ellipses="true" + use_ellipses="true" word_wrap="true" mouse_opaque="false" name="title" > - Select your streaming media preference. Select your streaming media preference. - </text> - + Beware the trout. BEWARE! THE! TROUT! + </text> <button - top="5" - left_pad="5" - width="15" - height="15" + top="5" + right="-5" + width="17" + height="17" layout="topleft" follows="right" - name="close_btn" + name="close_btn" mouse_opaque="true" - label="" tab_stop="false" - image_unselected="toast_hide_btn.tga" - image_disabled="toast_hide_btn.tga" - image_selected="toast_hide_btn.tga" - image_hover_selected="toast_hide_btn.tga" - image_disabled_selected="toast_hide_btn.tga" + image_unselected="Icon_Close_Toast" + image_selected="Icon_Close_Toast" /> - -</panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml index 63c2d4538e..73a7d95ff4 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml @@ -18,7 +18,7 @@ visible="false" width="380" /> <icon - height="20" + height="24" follows="top|right|left" image_name="ListItem_Select" layout="topleft" @@ -26,7 +26,7 @@ name="selected_icon" top="0" visible="false" - width="380" /> + width="320" /> <icon height="20" follows="top|right|left" @@ -46,21 +46,28 @@ name="region" text_color="white" top="4" - value="Unknown" - width="330" /> + value="..." + width="242" /> <button follows="right" - height="18" - image_disabled="Info" - image_disabled_selected="Info" - image_hover_selected="Info" - image_selected="Info" - image_unselected="Info" - layout="topleft" + height="16" + image_pressed="Info_Press" + image_unselected="Info_Over" + left_pad="3" + right="-31" name="info_btn" picture_style="true" - visible="false" - right="-5" - top="2" - width="18" /> + top_delta="-2" + width="16" /> + <button + follows="right" + height="20" + image_overlay="ForwardArrow_Off" + layout="topleft" + left_pad="5" + right="-3" + name="profile_btn" + picture_style="true" + top_delta="-2" + width="20" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_toast.xml b/indra/newview/skins/default/xui/en/panel_toast.xml index 2e500fc2aa..7f7777586c 100644 --- a/indra/newview/skins/default/xui/en/panel_toast.xml +++ b/indra/newview/skins/default/xui/en/panel_toast.xml @@ -1,70 +1,75 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <!-- All our XML is utf-8 encoded. --> +<!-- All this does is establish the position of the "close" button on the toast. --> + <floater + legacy_header_height="18" name="toast" title="" visible="false" layout="topleft" - width="350" - height="40" - left="100" - top="500" - follows="right|bottom" - bevel_style="in" + width="305" + left="0" + top="0" + follows="right|bottom" + bg_opaque_image="Toast_Background" + bg_alpha_image="Toast_Background" can_minimize="false" can_tear_off="false" can_resize="false" can_drag_on_left="false" can_close="false" - can_dock="false" + can_dock="false" + border_visible = "false" + border_drop_shadow_visible = "false" + drop_shadow_visible = "false" + border = "false" > + <!-- <text visible="false" follows="left|top|right|bottom" font="SansSerifBold" - height="28" + height="40" layout="topleft" left="60" name="toast_text" word_wrap="true" text_color="white" - top="10" + top="20" width="290"> Toast text; </text> <icon - top="4" - left="10" - width="32" + top="20" + left="10" + width="32" height="32" follows="top|left" layout="topleft" visible="false" - color="1 1 1 1" - enabled="true" + color="1 1 1 1" + enabled="true" image_name="notify_tip_icon.tga" - mouse_opaque="true" + mouse_opaque="true" name="icon" - /> + />--> <button layout="topleft" - top="-5" - left="335" - width="20" - height="20" + top="-6" + left="293" + width="17" + height="17" follows="top|right" - visible="false" - enabled="true" - mouse_opaque="true" - name="hide_btn" - label="" + visible="false" + enabled="true" + mouse_opaque="false" + name="hide_btn" + label="" tab_stop="false" - image_unselected="toast_hide_btn.tga" - image_disabled="toast_hide_btn.tga" - image_selected="toast_hide_btn.tga" - image_hover_selected="toast_hide_btn.tga" - image_disabled_selected="toast_hide_btn.tga" + image_unselected="Toast_CloseBtn" + image_selected="Toast_CloseBtn" /> -</floater> +</floater> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 4eacd72a7d..e842517853 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -74,6 +74,7 @@ <string name="TooltipTeleportUrl">Click to teleport to this location</string> <string name="TooltipObjectIMUrl">Click to view this object's description</string> <string name="TooltipSLAPP">Click to run the secondlife:// command</string> + <string name="CurrentURL" value=" CurrentURL: [CurrentURL]" /> <!-- ButtonToolTips, llfloater.cpp --> <string name="BUTTON_CLOSE_DARWIN">Close (⌘W)</string> @@ -636,7 +637,7 @@ Sets the script timer to zero float llGetAndResetTime() Returns the script time in seconds and then resets the script timer to zero </string> - <string name="LSLTipText_llSound" translate="false"> + <string name="LSLTipText_llSoplayund" translate="false"> llSound(string sound, float volume, integer queue, integer loop) Plays sound at volume and whether it should loop or not </string> @@ -2187,6 +2188,7 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh <!-- media --> <string name="Multiple Media">Multiple Media</string> + <string name="Play Media">Play/Pause Media</string> <!-- OSMessageBox messages --> <string name="MBCmdLineError"> diff --git a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml index dabcb1038b..fcfe89c653 100644 --- a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml @@ -9,4 +9,5 @@ header_image="Accordion_Off" header_image_over="Accordion_Over" header_image_pressed="Accordion_Press" + header_image_selected="Accordion_Selected" /> diff --git a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml index 319beac291..f59c46b2f5 100644 --- a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml +++ b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml @@ -3,7 +3,7 @@ max_height="300" > <textbox more_label="More" - follows="left|top" + follows="left|top|right" name="text" allow_scroll="true" use_ellipses="true" diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml index 4a866c2eb2..6660fbf1a8 100644 --- a/indra/newview/skins/default/xui/en/widgets/floater.xml +++ b/indra/newview/skins/default/xui/en/widgets/floater.xml @@ -1,6 +1,10 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- See also settings.xml UIFloater* settings for configuration --> <floater name="floater" bg_opaque_color="FloaterFocusBackgroundColor" bg_alpha_color="FloaterDefaultBackgroundColor" + bg_opaque_image="Window_Foreground" + bg_alpha_image="Window_Background" background_visible="true" - background_opaque="false"/> + background_opaque="false" + header_height="25" /> diff --git a/indra/newview/skins/default/xui/en/widgets/panel.xml b/indra/newview/skins/default/xui/en/widgets/panel.xml index b81a70b845..7262c0dc5c 100644 --- a/indra/newview/skins/default/xui/en/widgets/panel.xml +++ b/indra/newview/skins/default/xui/en/widgets/panel.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- Optional parameters: + border - show border around panel + bg_opaque_image - image name for "in-front" panel look + bg_alpha_image - image name for "in-back" or transparent panel look +--> <panel bg_opaque_color="PanelFocusBackgroundColor" bg_alpha_color="PanelDefaultBackgroundColor" background_visible="false" - background_opaque="false"/>
\ No newline at end of file + background_opaque="false" + chrome="false"/>
\ No newline at end of file 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 7d10df1af7..fe2f1423b7 100644 --- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml +++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <tab_container tab_min_width="60" tab_max_width="150" - font_halign="left" - tab_height="16"> + font_halign="center" + tab_height="21"> <first_tab tab_top_image_unselected="TabTop_Left_Off" tab_top_image_selected="TabTop_Left_Selected" tab_bottom_image_unselected="Toolbar_Left_Off" diff --git a/indra/newview/skins/default/xui/en/widgets/tool_tip.xml b/indra/newview/skins/default/xui/en/widgets/tool_tip.xml new file mode 100644 index 0000000000..6b49f832fd --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/tool_tip.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- See also settings.xml UIFloater* settings for configuration --> +<tool_tip name="tooltip" + max_width="200" + padding="4" + wrap="true" + font="SansSerif" + bg_opaque_color="ToolTipBgColor" + background_visible="true" + /> diff --git a/indra/test_apps/llplugintest/CMakeLists.txt b/indra/test_apps/llplugintest/CMakeLists.txt index 88c4ba8ad9..53b981cccd 100644 --- a/indra/test_apps/llplugintest/CMakeLists.txt +++ b/indra/test_apps/llplugintest/CMakeLists.txt @@ -293,6 +293,7 @@ add_dependencies(llmediaplugintest SLPlugin media_plugin_quicktime media_plugin_webkit + media_plugin_example ${LLPLUGIN_LIBRARIES} ${LLMESSAGE_LIBRARIES} ${LLCOMMON_LIBRARIES} @@ -369,6 +370,12 @@ if (DARWIN OR WINDOWS) DEPENDS ${BUILT_QUICKTIME_PLUGIN} ) + get_target_property(BUILT_EXAMPLE_PLUGIN media_plugin_example LOCATION) + add_custom_command(TARGET llmediaplugintest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_EXAMPLE_PLUGIN} ${PLUGINS_DESTINATION_DIR} + DEPENDS ${BUILT_EXAMPLE_PLUGIN} + ) + # copy over bookmarks file if llmediaplugintest gets built get_target_property(BUILT_LLMEDIAPLUGINTEST llmediaplugintest LOCATION) add_custom_command(TARGET llmediaplugintest POST_BUILD diff --git a/indra/test_apps/llplugintest/bookmarks.txt b/indra/test_apps/llplugintest/bookmarks.txt index ef34167b29..b8b83df386 100644 --- a/indra/test_apps/llplugintest/bookmarks.txt +++ b/indra/test_apps/llplugintest/bookmarks.txt @@ -34,3 +34,4 @@ (QT) Movie - The Informers,http://movies.apple.com/movies/independent/theinformers/theinformers_h.320.mov (QT) Animated GIF,http://upload.wikimedia.org/wikipedia/commons/4/44/Optical.greysquares.arp-animated.gif (QT) Apple Text Descriptors,http://ubrowser.com/tmp/apple_text.txt +(EX) Example Plugin,example://blah diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp index 553d1ab131..d987915bb8 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.cpp +++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -138,8 +138,6 @@ LLMediaPluginTest::LLMediaPluginTest( int app_window, int window_width, int wind mMediaBrowserControlBackButtonFlag( true ), mMediaBrowserControlForwardButtonFlag( true ), mHomeWebUrl( "http://www.google.com/" ) - //mHomeWebUrl( "file:///C|/Program Files/QuickTime/Sample.mov" ) - //mHomeWebUrl( "http://movies.apple.com/movies/wb/watchmen/watchmen-tlr2_480p.mov" ) { // debugging spam std::cout << std::endl << " GLUT version: " << "3.7.6" << std::endl; // no way to get real version from GLUT @@ -277,8 +275,6 @@ void LLMediaPluginTest::bindTexture(GLuint texture, GLint row_length, GLint alig { glEnable( GL_TEXTURE_2D ); -// std::cerr << "binding texture " << texture << std::endl; - glBindTexture( GL_TEXTURE_2D, texture ); glPixelStorei( GL_UNPACK_ROW_LENGTH, row_length ); glPixelStorei( GL_UNPACK_ALIGNMENT, alignment ); @@ -410,7 +406,7 @@ void LLMediaPluginTest::draw( int draw_type ) // only bother with pick if we have something to render // Actually, we need to pick even if we're not ready to render. // Otherwise you can't select and remove a panel which has gone bad. -// if ( mMediaPanels[ panel ]->mReadyToRender ) + //if ( mMediaPanels[ panel ]->mReadyToRender ) { glMatrixMode( GL_TEXTURE ); glPushMatrix(); @@ -621,10 +617,10 @@ void LLMediaPluginTest::idle() if ( mSelectedPanel ) { // set volume based on slider if we have time media -// if ( mGluiMediaTimeControlWindowFlag ) -// { -// mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f ); -// }; + //if ( mGluiMediaTimeControlWindowFlag ) + //{ + // mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f ); + //}; // NOTE: it is absurd that we need cache the state of GLUI controls // but enabling/disabling controls drags framerate from 500+ @@ -1463,6 +1459,9 @@ std::string LLMediaPluginTest::mimeTypeFromUrl( std::string& url ) else if ( url.find( ".txt" ) != std::string::npos ) // Apple Text descriptors mime_type = "video/quicktime"; + else + if ( url.find( "example://" ) != std::string::npos ) // Example plugin + mime_type = "example/example"; return mime_type; } @@ -1487,6 +1486,9 @@ std::string LLMediaPluginTest::pluginNameFromMimeType( std::string& mime_type ) else if ( mime_type == "text/html" ) plugin_name = "media_plugin_webkit.dll"; + else + if ( mime_type == "example/example" ) + plugin_name = "media_plugin_example.dll"; #elif LL_LINUX std::string plugin_name( "libmedia_plugin_null.so" ); @@ -1799,7 +1801,7 @@ void LLMediaPluginTest::getRandomMediaSize( int& width, int& height, std::string // adjust this random size if it's a browser so we get // a more useful size for testing.. - if ( mime_type == "text/html" ) + if ( mime_type == "text/html" || mime_type == "example/example" ) { width = ( ( rand() % 100 ) + 100 ) * 4; height = ( width * ( ( rand() % 400 ) + 1000 ) ) / 1000; |