diff options
74 files changed, 1431 insertions, 384 deletions
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 3ecab90756..88a1652671 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -101,6 +101,7 @@ set(llui_SOURCE_FILES lluictrlfactory.cpp lluiimage.cpp lluistring.cpp + lluitextutil.cpp llundo.cpp llurlaction.cpp llurlentry.cpp @@ -197,6 +198,7 @@ set(llui_HEADER_FILES llui.h lluiimage.h lluistring.h + lluitextutil.h llundo.h llurlaction.h llurlentry.h diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 596da782ce..0db2dca615 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -32,12 +32,13 @@ #include "linden_common.h" -#include "lluictrl.h" -#include "llscrollbar.h" #include "llaccordionctrltab.h" -#include "lllocalcliprect.h" +#include "lllocalcliprect.h" +#include "llscrollbar.h" #include "lltextbox.h" +#include "lluictrl.h" +#include "lluitextutil.h" static const std::string DD_BUTTON_NAME = "dd_button"; static const std::string DD_TEXTBOX_NAME = "dd_textbox"; @@ -72,7 +73,8 @@ public: virtual BOOL postBuild(); - void setTitle(const std::string& title); + std::string getTitle(); + void setTitle(const std::string& title, const std::string& hl); virtual void onMouseEnter(S32 x, S32 y, MASK mask); virtual void onMouseLeave(S32 x, S32 y, MASK mask); @@ -146,10 +148,28 @@ BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::postBuild() return TRUE; } -void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title) +std::string LLAccordionCtrlTab::LLAccordionCtrlTabHeader::getTitle() { if(mHeaderTextbox) - mHeaderTextbox->setText(title); + { + return mHeaderTextbox->getText(); + } + else + { + return LLStringUtil::null; + } +} + +void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title, const std::string& hl) +{ + if(mHeaderTextbox) + { + LLTextUtil::textboxSetHighlightedVal( + mHeaderTextbox, + LLStyle::Params(), + title, + hl); + } } void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw() @@ -436,12 +456,25 @@ void LLAccordionCtrlTab::setAccordionView(LLView* panel) addChild(panel,0); } -void LLAccordionCtrlTab::setTitle(const std::string& title) +std::string LLAccordionCtrlTab::getTitle() +{ + LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME); + if (header) + { + return header->getTitle(); + } + else + { + return LLStringUtil::null; + } +} + +void LLAccordionCtrlTab::setTitle(const std::string& title, const std::string& hl) { LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME); if (header) { - header->setTitle(title); + header->setTitle(title, hl); } } @@ -903,5 +936,3 @@ BOOL LLAccordionCtrlTab::handleToolTip(S32 x, S32 y, MASK mask) } return LLUICtrl::handleToolTip(x, y, mask); } - - diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index de254ed3eb..f5b7fd0af6 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -113,8 +113,10 @@ public: void setAccordionView(LLView* panel); LLView* getAccordionView() { return mContainerPanel; }; - // Set text in LLAccordionCtrlTabHeader - void setTitle(const std::string& title); + std::string getTitle(); + + // Set text and highlight substring in LLAccordionCtrlTabHeader + void setTitle(const std::string& title, const std::string& hl = LLStringUtil::null); boost::signals2::connection setFocusReceivedCallback(const focus_signal_t::slot_type& cb); boost::signals2::connection setFocusLostCallback(const focus_signal_t::slot_type& cb); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index e0e86ae228..b77126996e 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3420,6 +3420,12 @@ BOOL LLMenuHolderGL::handleKey(KEY key, MASK mask, BOOL called_from_parent) if (pMenu) { + //eat TAB key - EXT-7000 + if (key == KEY_TAB && mask == MASK_NONE) + { + return TRUE; + } + //handle ESCAPE and RETURN key handled = LLPanel::handleKey(key, mask, called_from_parent); if (!handled) @@ -3726,10 +3732,14 @@ void LLContextMenuBranch::buildDrawLabel( void ) void LLContextMenuBranch::showSubMenu() { - S32 center_x; - S32 center_y; - localPointToScreen(getRect().getWidth(), getRect().getHeight() , ¢er_x, ¢er_y); - mBranch->show( center_x, center_y); + LLMenuItemGL* menu_item = mBranch->getParentMenuItem(); + if (menu_item != NULL && menu_item->getVisible()) + { + S32 center_x; + S32 center_y; + localPointToScreen(getRect().getWidth(), getRect().getHeight() , ¢er_x, ¢er_y); + mBranch->show(center_x, center_y); + } } // onCommit() - do the primary funcationality of the menu item. diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4e4c0274e7..f71662a7c8 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3578,6 +3578,17 @@ <key>Value</key> <integer>1024</integer> </map> + <key>GesturesMarketplaceURL</key> + <map> + <key>Comment</key> + <string>URL to the Gestures Marketplace</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>https://www.xstreetsl.com/modules.php?name=Marketplace&CategoryID=233</string> + </map> <key>GridCrossSections</key> <map> <key>Comment</key> diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index bcaba34921..4aef72ab0b 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -55,6 +55,25 @@ char ORDER_NUMBER_SEPARATOR('@'); +// support for secondlife:///app/appearance SLapps +class LLAppearanceHandler : public LLCommandHandler +{ +public: + // requests will be throttled from a non-trusted browser + LLAppearanceHandler() : LLCommandHandler("appearance", UNTRUSTED_THROTTLE) {} + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + // support secondlife:///app/appearance/show, but for now we just + // make all secondlife:///app/appearance SLapps behave this way + LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD()); + return true; + } +}; + +LLAppearanceHandler gAppearanceHandler; + + LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id, const std::string& name) { LLInventoryModel::cat_array_t cat_array; @@ -505,6 +524,7 @@ bool LLWearableHoldingPattern::pollMissingWearables() if (done) { + gAgentAvatarp->wearablesLoaded(); clearCOFLinksForMissingWearables(); onAllComplete(); } @@ -1630,6 +1650,7 @@ void LLAppearanceMgr::autopopulateOutfits() // Handler for anything that's deferred until avatar de-clouds. void LLAppearanceMgr::onFirstFullyVisible() { + gAgentAvatarp->avatarVisible(); autopopulateOutfits(); } diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index dfb213716c..72ee289c91 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -316,9 +316,7 @@ void LLAvatarList::refresh() } // Send refresh_complete signal. - std::vector<LLSD> cur_values; - getValues(cur_values); - mRefreshCompleteSignal(this, LLSD((S32)cur_values.size())); + mRefreshCompleteSignal(this, LLSD((S32)size(false))); } // Commit if we've added/removed items. @@ -401,6 +399,15 @@ BOOL LLAvatarList::handleRightMouseDown(S32 x, S32 y, MASK mask) return handled; } +void LLAvatarList::setVisible(BOOL visible) +{ + if ( visible == FALSE && mContextMenu ) + { + mContextMenu->hide(); + } + LLFlatListViewEx::setVisible(visible); +} + void LLAvatarList::computeDifference( const uuid_vec_t& vnew_unsorted, uuid_vec_t& vadded, diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index ff090f3a34..a9320055ca 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -70,6 +70,8 @@ public: virtual void clear(); + virtual void setVisible(BOOL visible); + void setNameFilter(const std::string& filter); void setDirty(bool val = true, bool force_refresh = false); uuid_vec_t& getIDs() { return mIDs; } diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 2a51eeacfc..656274cb7a 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -36,12 +36,13 @@ #include "llavataractions.h" #include "llavatarlistitem.h" +#include "llbutton.h" #include "llfloaterreg.h" +#include "lluitextutil.h" + #include "llagent.h" -#include "lloutputmonitorctrl.h" #include "llavatariconctrl.h" -#include "lltextutil.h" -#include "llbutton.h" +#include "lloutputmonitorctrl.h" bool LLAvatarListItem::sStaticInitialized = false; S32 LLAvatarListItem::sLeftPadding = 0; diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 3ba2c7a3e3..c6fac7a9f1 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -71,6 +71,7 @@ public: { public: virtual void show(LLView* spawning_view, const uuid_vec_t& selected_uuids, S32 x, S32 y) = 0; + virtual void hide() = 0; }; /** diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 226d5593c9..7f528c88b2 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -479,6 +479,10 @@ BOOL LLBottomTray::postBuild() initResizeStateContainers(); + setButtonsControlsAndListeners(); + + initButtonsVisibility(); + // update wells visibility: showWellButton(RS_IM_WELL, !LLIMWellWindow::getInstance()->isWindowEmpty()); showWellButton(RS_NOTIFICATION_WELL, !LLNotificationWellWindow::getInstance()->isWindowEmpty()); @@ -1091,52 +1095,108 @@ void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32& bool LLBottomTray::canButtonBeShown(EResizeState processed_object_type) const { + // 0. Check if passed button was previously hidden on resize bool can_be_shown = mResizeState & processed_object_type; if (can_be_shown) { - static MASK MOVEMENT_PREVIOUS_BUTTONS_MASK = RS_BUTTON_GESTURES; - static MASK CAMERA_PREVIOUS_BUTTONS_MASK = RS_BUTTON_GESTURES | RS_BUTTON_MOVEMENT; - static MASK SNAPSHOT_PREVIOUS_BUTTONS_MASK = RS_BUTTON_GESTURES | RS_BUTTON_MOVEMENT | RS_BUTTON_CAMERA; + // Yes, it was. Lets now check that all buttons before it (that can be hidden on resize) + // are already shown + + // process buttons in direct order (from left to right) + resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin(); + const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end(); - switch(processed_object_type) + // 1. Find and accumulate all buttons types before one passed into the method. + MASK buttons_before_mask = RS_NORESIZE; + for (; it != it_end; ++it) { - case RS_BUTTON_GESTURES: // Gestures should be shown first - break; - case RS_BUTTON_MOVEMENT: // Move only if gesture is shown - can_be_shown = !(MOVEMENT_PREVIOUS_BUTTONS_MASK & mResizeState); - break; - case RS_BUTTON_CAMERA: - can_be_shown = !(CAMERA_PREVIOUS_BUTTONS_MASK & mResizeState); - break; - case RS_BUTTON_SNAPSHOT: - can_be_shown = !(SNAPSHOT_PREVIOUS_BUTTONS_MASK & mResizeState); - break; - default: // nothing to do here - break; + const EResizeState button_type = *it; + if (button_type == processed_object_type) break; + + buttons_before_mask |= button_type; } + + // 2. Check if some previous buttons are still hidden on resize + can_be_shown = !(buttons_before_mask & mResizeState); } return can_be_shown; } void LLBottomTray::initResizeStateContainers() { + // *TODO: get rid of mGesturePanel, mMovementPanel, mCamPanel, mSnapshotPanel instance members // init map with objects should be processed for each type mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_GESTURES, mGesturePanel)); mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MOVEMENT, mMovementPanel)); mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_CAMERA, mCamPanel)); mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SNAPSHOT, mSnapshotPanel)); - - // init default widths - mObjectDefaultWidthMap[RS_BUTTON_GESTURES] = mGesturePanel->getRect().getWidth(); - mObjectDefaultWidthMap[RS_BUTTON_MOVEMENT] = mMovementPanel->getRect().getWidth(); - mObjectDefaultWidthMap[RS_BUTTON_CAMERA] = mCamPanel->getRect().getWidth(); - mObjectDefaultWidthMap[RS_BUTTON_SPEAK] = mSpeakPanel->getRect().getWidth(); + mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_BUILD, getChild<LLPanel>("build_btn_panel"))); + mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SEARCH, getChild<LLPanel>("search_btn_panel"))); + mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_WORLD_MAP, getChild<LLPanel>("world_map_btn_panel"))); + mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MINI_MAP, getChild<LLPanel>("mini_map_btn_panel"))); // init an order of processed buttons mButtonsProcessOrder.push_back(RS_BUTTON_GESTURES); mButtonsProcessOrder.push_back(RS_BUTTON_MOVEMENT); mButtonsProcessOrder.push_back(RS_BUTTON_CAMERA); mButtonsProcessOrder.push_back(RS_BUTTON_SNAPSHOT); + mButtonsProcessOrder.push_back(RS_BUTTON_BUILD); + mButtonsProcessOrder.push_back(RS_BUTTON_SEARCH); + mButtonsProcessOrder.push_back(RS_BUTTON_WORLD_MAP); + mButtonsProcessOrder.push_back(RS_BUTTON_MINI_MAP); + + // init default widths + + // process buttons that can be hidden on resize... + resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin(); + const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end(); + + for (; it != it_end; ++it) + { + const EResizeState button_type = *it; + // is there an appropriate object? + if (0 == mStateProcessedObjectMap.count(button_type)) continue; + + // set default width for it. + mObjectDefaultWidthMap[button_type] = mStateProcessedObjectMap[button_type]->getRect().getWidth(); + } + + // ... and add Speak button because it also can be shrunk. + mObjectDefaultWidthMap[RS_BUTTON_SPEAK] = mSpeakPanel->getRect().getWidth(); + +} + +void LLBottomTray::initButtonsVisibility() +{ + // *TODO: move control settings of other buttons here + setTrayButtonVisibleIfPossible(RS_BUTTON_BUILD, gSavedSettings.getBOOL("ShowBuildButton")); + setTrayButtonVisibleIfPossible(RS_BUTTON_SEARCH, gSavedSettings.getBOOL("ShowSearchButton")); + setTrayButtonVisibleIfPossible(RS_BUTTON_WORLD_MAP, gSavedSettings.getBOOL("ShowWorldMapButton")); + setTrayButtonVisibleIfPossible(RS_BUTTON_MINI_MAP, gSavedSettings.getBOOL("ShowMiniMapButton")); +} + +void LLBottomTray::setButtonsControlsAndListeners() +{ + // *TODO: move control settings of other buttons here + gSavedSettings.declareBOOL("ShowBuildButton", TRUE, "Shows/Hides Build button in the bottom tray. (Declared in code)"); + gSavedSettings.declareBOOL("ShowSearchButton", TRUE, "Shows/Hides Search button in the bottom tray. (Declared in code)"); + gSavedSettings.declareBOOL("ShowWorldMapButton", TRUE, "Shows/Hides Map button in the bottom tray. (Declared in code)"); + gSavedSettings.declareBOOL("ShowMiniMapButton", TRUE, "Shows/Hides Mini-Map button in the bottom tray. (Declared in code)"); + + + gSavedSettings.getControl("ShowBuildButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_BUILD, _2)); + gSavedSettings.getControl("ShowSearchButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SEARCH, _2)); + gSavedSettings.getControl("ShowWorldMapButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_WORLD_MAP, _2)); + gSavedSettings.getControl("ShowMiniMapButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_MINI_MAP, _2)); +} + +bool LLBottomTray::toggleShowButton(LLBottomTray::EResizeState button_type, const LLSD& new_visibility) +{ + if (LLBottomTray::instanceExists()) + { + LLBottomTray::getInstance()->setTrayButtonVisibleIfPossible(button_type, new_visibility.asBoolean()); + } + return true; } void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool visible) diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index e9d59e82ba..5588aefb42 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -120,12 +120,24 @@ private: , RS_BUTTON_SPEAK = 0x0040 , RS_IM_WELL = 0x0080 , RS_NOTIFICATION_WELL = 0x0100 + , RS_BUTTON_BUILD = 0x0200 + , RS_BUTTON_SEARCH = 0x0400 + , RS_BUTTON_WORLD_MAP = 0x0800 + , RS_BUTTON_MINI_MAP = 0x1000 + + /* + Once new button that can be hidden on resize is added don't forget to update related places: + - RS_BUTTONS_CAN_BE_HIDDEN enum value below. + - initResizeStateContainers(): mStateProcessedObjectMap and mButtonsProcessOrder + */ /** * Specifies buttons which can be hidden when bottom tray is shrunk. * They are: Gestures, Movement (Move), Camera (View), Snapshot + * new: Build, Search, Map, World Map, Mini-Map. */ , RS_BUTTONS_CAN_BE_HIDDEN = RS_BUTTON_SNAPSHOT | RS_BUTTON_CAMERA | RS_BUTTON_MOVEMENT | RS_BUTTON_GESTURES + | RS_BUTTON_BUILD | RS_BUTTON_SEARCH | RS_BUTTON_WORLD_MAP | RS_BUTTON_MINI_MAP }EResizeState; /** @@ -272,6 +284,28 @@ private: void initResizeStateContainers(); /** + * Initializes buttons' visibility depend on stored Control Settings. + */ + void initButtonsVisibility(); + + /** + * Initializes listeners of Control Settings to toggle appropriate buttons' visibility. + * + * @see toggleShowButton() + */ + void setButtonsControlsAndListeners(); + + /** + * Toggles visibility of specified button depend on passed value. + * + * @param button_type - type of button to be toggled + * @param new_visibility - new visibility of the button + * + * @see setButtonsControlsAndListeners() + */ + static bool toggleShowButton(EResizeState button_type, const LLSD& new_visibility); + + /** * Sets passed visibility to object specified by resize type. */ void setTrayButtonVisible(EResizeState shown_object_type, bool visible); diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 5b6a99e793..35a244c461 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -326,12 +326,14 @@ void LLNearbyChatToastPanel::draw() if(icon) { icon->setDrawTooltip(mSourceType == CHAT_SOURCE_AGENT); - if(mSourceType == CHAT_SOURCE_AGENT) - icon->setValue(mFromID); + if(mSourceType == CHAT_SOURCE_OBJECT) + icon->setValue(LLSD("OBJECT_Icon")); else if(mSourceType == CHAT_SOURCE_SYSTEM) icon->setValue(LLSD("SL_Logo")); - else - icon->setValue(LLSD("OBJECT_Icon")); + else if(mSourceType == CHAT_SOURCE_AGENT) + icon->setValue(mFromID); + else if(!mFromID.isNull()) + icon->setValue(mFromID); } mIsDirty = false; } diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 9c4aa7b964..6897f4ee8e 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -183,20 +183,6 @@ void LLSysWellChiclet::setCounter(S32 counter) mButton->setLabel(s_count); - setNewMessagesState(counter > mCounter); - - // we have to flash to 'Lit' state each time new unread message is coming. - if (counter > mCounter) - { - mFlashToLitTimer->flash(); - } - else if (counter == 0) - { - // if notification is resolved while well is flashing it can leave in the 'Lit' state - // when flashing finishes itself. Let break flashing here. - mFlashToLitTimer->stopFlashing(); - } - mCounter = counter; } @@ -316,7 +302,26 @@ void LLIMWellChiclet::createMenu() void LLIMWellChiclet::messageCountChanged(const LLSD& session_data) { - setCounter(LLBottomTray::getInstance()->getTotalUnreadIMCount()); + const LLUUID& session_id = session_data["session_id"]; + const S32 counter = LLBottomTray::getInstance()->getTotalUnreadIMCount(); + const bool im_not_visible = !LLFloaterReg::instanceVisible("im_container") + && !LLFloaterReg::instanceVisible("impanel", session_id); + + setNewMessagesState(counter > mCounter && im_not_visible); + + // we have to flash to 'Lit' state each time new unread message is coming. + if (counter > mCounter && im_not_visible) + { + mFlashToLitTimer->flash(); + } + else if (counter == 0) + { + // if notification is resolved while well is flashing it can leave in the 'Lit' state + // when flashing finishes itself. Let break flashing here. + mFlashToLitTimer->stopFlashing(); + } + + setCounter(counter); } /************************************************************************/ diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index 498aeec682..8d4430a9ea 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -46,6 +46,20 @@ static LLRegisterPanelClassWrapper<LLCOFWearables> t_cof_wearables("cof_wearable const LLSD REARRANGE = LLSD().with("rearrange", LLSD()); +static const LLWearableItemNameComparator WEARABLE_NAME_COMPARATOR; + + +bool LLWearableItemNameComparator::doCompare(const LLPanelWearableListItem* wearable_item1, const LLPanelWearableListItem* wearable_item2) const +{ + std::string name1 = wearable_item1->getItemName(); + std::string name2 = wearable_item2->getItemName(); + + LLStringUtil::toUpper(name1); + LLStringUtil::toUpper(name2); + + return name1 < name2; +} + LLCOFWearables::LLCOFWearables() : LLPanel(), mAttachments(NULL), @@ -73,6 +87,10 @@ BOOL LLCOFWearables::postBuild() mClothing->setCommitOnSelectionChange(true); mBodyParts->setCommitOnSelectionChange(true); + //clothing is sorted according to its position relatively to the body + mAttachments->setComparator(&WEARABLE_NAME_COMPARATOR); + mBodyParts->setComparator(&WEARABLE_NAME_COMPARATOR); + return LLPanel::postBuild(); } @@ -164,16 +182,15 @@ void LLCOFWearables::populateAttachmentsAndBodypartsLists(const LLInventoryModel if (mAttachments->size()) { - mAttachments->sort(); //*TODO by Name + mAttachments->sort(); mAttachments->notify(REARRANGE); //notifying the parent about the list's size change (cause items were added with rearrange=false) } if (mBodyParts->size()) { - mBodyParts->sort(); //*TODO by name + mBodyParts->sort(); + mBodyParts->notify(REARRANGE); } - - mBodyParts->notify(REARRANGE); } //create a clothing list item, update verbs and show/hide line separator diff --git a/indra/newview/llcofwearables.h b/indra/newview/llcofwearables.h index 32acba5a3e..612bb103d2 100644 --- a/indra/newview/llcofwearables.h +++ b/indra/newview/llcofwearables.h @@ -40,6 +40,53 @@ class LLFlatListView; + +/** Abstract comparator of wearable list items */ +class LLWearableListItemComparator : public LLFlatListView::ItemComparator +{ + LOG_CLASS(LLWearableListItemComparator); + +public: + LLWearableListItemComparator() {}; + virtual ~LLWearableListItemComparator() {}; + + virtual bool compare(const LLPanel* item1, const LLPanel* item2) const + { + const LLPanelWearableListItem* wearable_item1 = dynamic_cast<const LLPanelWearableListItem*>(item1); + const LLPanelWearableListItem* wearable_item2 = dynamic_cast<const LLPanelWearableListItem*>(item2); + + if (!wearable_item1 || !wearable_item2) + { + llwarning("item1 and item2 cannot be null", 0); + return true; + } + + return doCompare(wearable_item1, wearable_item2); + } + +protected: + + /** + * Returns true if wearable_item1 < wearable_item2, false otherwise + * Implement this method in your particular comparator. + */ + virtual bool doCompare(const LLPanelWearableListItem* wearable_item1, const LLPanelWearableListItem* wearable_item2) const = 0; +}; + + +class LLWearableItemNameComparator : public LLWearableListItemComparator +{ + LOG_CLASS(LLWearableItemNameComparator); + +public: + LLWearableItemNameComparator() {}; + virtual ~LLWearableItemNameComparator() {}; + +protected: + virtual bool doCompare(const LLPanelWearableListItem* wearable_item1, const LLPanelWearableListItem* wearable_item2) const; +}; + + /** * Adaptor between LLAccordionCtrlTab and LLFlatListView to facilitate communication between them * (notify, notifyParent) regarding size changes of a list and selection changes across accordion tabs. diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 2ae11aa2b5..a87f7288fa 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -1744,6 +1744,8 @@ BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) mParentPanel->setFocus(TRUE); + LLEditMenuHandler::gEditMenuHandler = this; + return LLView::handleMouseDown( x, y, mask ); } diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 5efd99b939..3224ac6d9b 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -40,12 +40,12 @@ #include "llmenugl.h" #include "lltextbox.h" #include "lltrans.h" +#include "lluitextutil.h" // newview #include "llagent.h" #include "llgroupactions.h" #include "llfloaterreg.h" -#include "lltextutil.h" #include "llviewercontrol.h" // for gSavedSettings #include "llviewermenu.h" // for gMenuHolder #include "llvoiceclient.h" diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index d25aa37e16..3aa9d75bc0 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -1104,6 +1104,21 @@ void LLIMFloater::closeHiddenIMToasts() channel->closeHiddenToasts(IMToastMatcher()); } } +// static +void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + const LLSD& payload = notification["payload"]; + LLUUID session_id = payload["session_id"]; + + LLFloater* im_floater = LLFloaterReg::findInstance("impanel", session_id); + if (option == 0 && im_floater != NULL) + { + im_floater->closeFloater(); + } + + return; +} // static bool LLIMFloater::isChatMultiTab() @@ -1176,7 +1191,7 @@ void LLIMFloater::onClickCloseBtn() { LLSD payload; payload["session_id"] = mSessionID; - LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload); + LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); return; } diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index d63246a5cd..fef178e3a2 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -155,6 +155,8 @@ private: static void closeHiddenIMToasts(); + static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); + LLPanelChatControlPanel* mControlPanel; LLUUID mSessionID; S32 mLastMessageIndex; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 973257b19c..b9b4fa8b03 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -143,7 +143,6 @@ const std::string& LLInvFVBridge::getDisplayName() const // Folders have full perms PermissionMask LLInvFVBridge::getPermissionMask() const { - return PERM_ALL; } @@ -1219,18 +1218,7 @@ 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; - - } + if (item) perm_mask = item->getPermissionMask(); return perm_mask; } diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 901a570487..c90919e8fd 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -41,6 +41,7 @@ #include "llinventorymodelbackgroundfetch.h" #include "llviewercontrol.h" #include "llfolderview.h" +#include "llinventorybridge.h" // linden library includes #include "lltrans.h" @@ -54,7 +55,8 @@ LLInventoryFilter::FilterOps::FilterOps() : mShowFolderState(SHOW_NON_EMPTY_FOLDERS), mPermissions(PERM_NONE), mFilterTypes(FILTERTYPE_OBJECT), - mFilterUUID(LLUUID::null) + mFilterUUID(LLUUID::null), + mIncludeLinks(TRUE) { } @@ -97,23 +99,23 @@ BOOL LLInventoryFilter::check(const LLFolderViewItem* item) return TRUE; } - const LLFolderViewEventListener* listener = item->getListener(); mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; const BOOL passed_filtertype = checkAgainstFilterType(item); - const BOOL passed = passed_filtertype && - (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos) && - ((listener->getPermissionMask() & mFilterOps.mPermissions) == mFilterOps.mPermissions); + const BOOL passed_permissions = checkAgainstPermissions(item); + const BOOL passed = (passed_filtertype && + passed_permissions && + (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); return passed; } -BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) +BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const { const LLFolderViewEventListener* listener = item->getListener(); if (!listener) return FALSE; - const LLInventoryType::EType object_type = listener->getInventoryType(); + LLInventoryType::EType object_type = listener->getInventoryType(); const LLUUID object_id = listener->getUUID(); const LLInventoryObject *object = gInventory.getObject(object_id); @@ -128,7 +130,9 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) if (object_type == LLInventoryType::IT_NONE) { if (object && object->getIsLinkType()) + { return FALSE; + } } else if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0)) { @@ -203,6 +207,22 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) return TRUE; } +BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const +{ + const LLFolderViewEventListener* listener = item->getListener(); + if (!listener) return FALSE; + + PermissionMask perm = listener->getPermissionMask(); + const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(item->getListener()); + if (bridge && bridge->isLink()) + { + const LLUUID& linked_uuid = gInventory.getLinkedItemID(bridge->getUUID()); + const LLViewerInventoryItem *linked_item = gInventory.getItem(linked_uuid); + if (linked_item) + perm = linked_item->getPermissionMask(); + } + return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions; +} const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const { @@ -451,6 +471,18 @@ void LLInventoryFilter::setHoursAgo(U32 hours) mFilterOps.mFilterTypes |= FILTERTYPE_DATE; } +void LLInventoryFilter::setIncludeLinks(BOOL include_links) +{ + if (mFilterOps.mIncludeLinks != include_links) + { + if (!mFilterOps.mIncludeLinks) + setModified(FILTER_LESS_RESTRICTIVE); + else + setModified(FILTER_MORE_RESTRICTIVE); + } + mFilterOps.mIncludeLinks = include_links; +} + void LLInventoryFilter::setShowFolderState(EFolderShow state) { if (mFilterOps.mShowFolderState != state) @@ -826,6 +858,10 @@ U32 LLInventoryFilter::getHoursAgo() const { return mFilterOps.mHoursAgo; } +BOOL LLInventoryFilter::getIncludeLinks() const +{ + return mFilterOps.mIncludeLinks; +} LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const { return mFilterOps.mShowFolderState; diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 2376ba5d22..3ef51baefc 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -98,11 +98,15 @@ public: void setHoursAgo(U32 hours); U32 getHoursAgo() const; + void setIncludeLinks(BOOL include_links); + BOOL getIncludeLinks() const; + // +-------------------------------------------------------------------+ // + Execution And Results // +-------------------------------------------------------------------+ BOOL check(const LLFolderViewItem* item); - BOOL checkAgainstFilterType(const LLFolderViewItem* item); + BOOL checkAgainstFilterType(const LLFolderViewItem* item) const; + BOOL checkAgainstPermissions(const LLFolderViewItem* item) const; std::string::size_type getStringMatchOffset() const; // +-------------------------------------------------------------------+ @@ -172,6 +176,7 @@ private: U32 mHoursAgo; EFolderShow mShowFolderState; PermissionMask mPermissions; + BOOL mIncludeLinks; }; U32 mOrder; diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp index f48e7b3966..9b592e79af 100644 --- a/indra/newview/llinventoryitemslist.cpp +++ b/indra/newview/llinventoryitemslist.cpp @@ -40,11 +40,13 @@ // llcommon #include "llcommonutils.h" +// llui #include "lliconctrl.h" +#include "lluitextutil.h" +#include "llcallbacklist.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" -#include "lltextutil.h" #include "lltrans.h" //////////////////////////////////////////////////////////////////////////////// @@ -320,6 +322,7 @@ LLInventoryItemsList::Params::Params() LLInventoryItemsList::LLInventoryItemsList(const LLInventoryItemsList::Params& p) : LLFlatListViewEx(p) , mNeedsRefresh(false) +, mForceRefresh(false) { // TODO: mCommitOnSelectionChange is set to "false" in LLFlatListView // but reset to true in all derived classes. This settings might need to @@ -327,6 +330,8 @@ LLInventoryItemsList::LLInventoryItemsList(const LLInventoryItemsList::Params& p setCommitOnSelectionChange(true); setNoFilteredItemsMsg(LLTrans::getString("InventoryNoMatchingItems")); + + gIdleCallbacks.addFunction(idle, this); } // virtual @@ -344,12 +349,30 @@ void LLInventoryItemsList::refreshList(const LLInventoryModel::item_array_t item mNeedsRefresh = true; } -void LLInventoryItemsList::draw() +boost::signals2::connection LLInventoryItemsList::setRefreshCompleteCallback(const commit_signal_t::slot_type& cb) { - LLFlatListViewEx::draw(); - if(mNeedsRefresh) + return mRefreshCompleteSignal.connect(cb); +} + +void LLInventoryItemsList::doIdle() +{ + if (!mNeedsRefresh) return; + + if (isInVisibleChain() || mForceRefresh) { refresh(); + + mRefreshCompleteSignal(this, LLSD()); + } +} + +//static +void LLInventoryItemsList::idle(void* user_data) +{ + LLInventoryItemsList* self = static_cast<LLInventoryItemsList*>(user_data); + if ( self ) + { // Do the real idle + self->doIdle(); } } @@ -390,6 +413,7 @@ void LLInventoryItemsList::refresh() bool needs_refresh = add_limit_exceeded; setNeedsRefresh(needs_refresh); + setForceRefresh(needs_refresh); } void LLInventoryItemsList::computeDifference( diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h index bc04eb6f5b..a3863b511c 100644 --- a/indra/newview/llinventoryitemslist.h +++ b/indra/newview/llinventoryitemslist.h @@ -42,6 +42,7 @@ // newview #include "llflatlistview.h" +#include "llviewerinventory.h" class LLIconCtrl; class LLTextBox; @@ -120,6 +121,9 @@ public: /* Removes item highlight */ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); + /** Get the name of a corresponding inventory item */ + const std::string& getItemName() const { return mItem->getName(); } + virtual ~LLPanelInventoryListItemBase(){} protected: @@ -208,14 +212,29 @@ public: void refreshList(const LLDynamicArray<LLPointer<LLViewerInventoryItem> > item_array); + boost::signals2::connection setRefreshCompleteCallback(const commit_signal_t::slot_type& cb); + /** - * Let list know items need to be refreshed in next draw() + * Let list know items need to be refreshed in next doIdle() */ void setNeedsRefresh(bool needs_refresh){ mNeedsRefresh = needs_refresh; } bool getNeedsRefresh(){ return mNeedsRefresh; } - /*virtual*/ void draw(); + /** + * Sets the flag indicating that the list needs to be refreshed even if it is + * not currently visible. + */ + void setForceRefresh(bool force_refresh){ mForceRefresh = force_refresh; } + + /** + * Idle routine used to refresh the list regardless of the current list + * visibility, unlike draw() which is called only for the visible list. + * This is needed for example to filter items of the list hidden by closed + * accordion tab. + */ + void doIdle(); // Real idle routine + static void idle(void* user_data); // static glue to doIdle() protected: friend class LLUICtrlFactory; @@ -225,7 +244,7 @@ protected: /** * Refreshes list items, adds new items and removes deleted items. - * Called from draw() until all new items are added, , + * Called from doIdle() until all new items are added, * maximum 50 items can be added during single call. */ void refresh(); @@ -245,6 +264,10 @@ private: uuid_vec_t mIDs; // IDs of items that were added in refreshList(). // Will be used in refresh() to determine added and removed ids bool mNeedsRefresh; + + bool mForceRefresh; + + commit_signal_t mRefreshCompleteSignal; }; #endif //LL_LLINVENTORYITEMSLIST_H diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 5f5d4d6118..1f7bd50328 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -256,7 +256,7 @@ public: // updateCategory() method to actually modify values. LLViewerInventoryCategory* getCategory(const LLUUID& id) const; - // Get the inventoryID that this item points to, else just return item_id. + // Get the inventoryID or item that this item points to, else just return object_id const LLUUID& getLinkedItemID(const LLUUID& object_id) const; private: mutable LLPointer<LLViewerInventoryItem> mLastItem; // cache recent lookups diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index c24d2ee0ea..8557548887 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -493,7 +493,7 @@ void LLInventoryExistenceObserver::changed(U32 mask) } } -void LLInventoryMoveFromWorldObserver::changed(U32 mask) +void LLInventoryAddItemByAssetObserver::changed(U32 mask) { if(!(mask & LLInventoryObserver::ADD)) { @@ -535,7 +535,7 @@ void LLInventoryMoveFromWorldObserver::changed(U32 mask) } } -void LLInventoryMoveFromWorldObserver::watchAsset(const LLUUID& asset_id) +void LLInventoryAddItemByAssetObserver::watchAsset(const LLUUID& asset_id) { if(asset_id.notNull()) { @@ -551,7 +551,7 @@ void LLInventoryMoveFromWorldObserver::watchAsset(const LLUUID& asset_id) } } -bool LLInventoryMoveFromWorldObserver::isAssetWatched( const LLUUID& asset_id ) +bool LLInventoryAddItemByAssetObserver::isAssetWatched( const LLUUID& asset_id ) { return std::find(mWatchedAssets.begin(), mWatchedAssets.end(), asset_id) != mWatchedAssets.end(); } diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index 036e6ca40d..6d5a86a6fc 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -180,10 +180,10 @@ protected: // something useful. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryMoveFromWorldObserver : public LLInventoryObserver +class LLInventoryAddItemByAssetObserver : public LLInventoryObserver { public: - LLInventoryMoveFromWorldObserver() : mIsDirty(false) {} + LLInventoryAddItemByAssetObserver() : mIsDirty(false) {} virtual void changed(U32 mask); void watchAsset(const LLUUID& asset_id); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 000bcdd265..4766c1c227 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -248,6 +248,11 @@ void LLInventoryPanel::setHoursAgo(U32 hours) getFilter()->setHoursAgo(hours); } +void LLInventoryPanel::setIncludeLinks(BOOL include_links) +{ + getFilter()->setIncludeLinks(include_links); +} + void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show) { getFilter()->setShowFolderState(show); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 160a3d6f23..4373cedf66 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -141,7 +141,8 @@ public: void setSinceLogoff(BOOL sl); void setHoursAgo(U32 hours); BOOL getSinceLogoff(); - + void setIncludeLinks(BOOL include_links); + void setShowFolderState(LLInventoryFilter::EFolderShow show); LLInventoryFilter::EFolderShow getShowFolderState(); void setAllowMultiSelect(BOOL allow) { mFolderRoot->setAllowMultiSelect(allow); } diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 1507b7d324..bd504906d5 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -79,6 +79,7 @@ LLGestureComboList::LLGestureComboList(const LLGestureComboList::Params& p) : LLUICtrl(p) , mLabel(p.label) , mViewAllItemIndex(0) + , mGetMoreItemIndex(0) { LLButton::Params button_params = p.combo_button; button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT); @@ -260,9 +261,12 @@ void LLGestureComboList::refreshGestures() sortByName(); - // store index followed by the last added Gesture and add View All item at bottom - mViewAllItemIndex = idx; - + // store indices for Get More and View All items (idx is the index followed by the last added Gesture) + mGetMoreItemIndex = idx; + mViewAllItemIndex = idx + 1; + + // add Get More and View All items at the bottom + mList->addSimpleElement(LLTrans::getString("GetMoreGestures"), ADD_BOTTOM, LLSD(mGetMoreItemIndex)); mList->addSimpleElement(LLTrans::getString("ViewAllGestures"), ADD_BOTTOM, LLSD(mViewAllItemIndex)); // Insert label after sorting, at top, with separator below it @@ -318,6 +322,12 @@ void LLGestureComboList::onCommitGesture() return; } + if (mGetMoreItemIndex == index) + { + LLWeb::loadURLExternal(gSavedSettings.getString("GesturesMarketplaceURL")); + return; + } + LLMultiGesture* gesture = mGestures.at(index); if(gesture) { diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index dd467d7978..5af3152662 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -62,6 +62,7 @@ protected: std::vector<LLMultiGesture*> mGestures; std::string mLabel; LLSD::Integer mViewAllItemIndex; + LLSD::Integer mGetMoreItemIndex; public: diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 18bd610dd9..43b7e15977 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -169,12 +169,30 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) // Setting list commit callback to monitor currently selected wearable item. list->setCommitCallback(boost::bind(&LLOutfitsList::onSelectionChange, this, _1)); + // Setting list refresh callback to apply filter on list change. + list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1)); + // Fetch the new outfit contents. cat->fetch(); // Refresh the list of outfit items after fetch(). // Further list updates will be triggered by the category observer. list->updateList(cat_id); + + // If filter is currently applied we store the initial tab state and + // open it to show matched items if any. + if (!mFilterSubString.empty()) + { + tab->notifyChildren(LLSD().with("action","store_state")); + tab->setDisplayChildren(true); + + // Setting mForceRefresh flag will make the list refresh its contents + // even if it is not currently visible. This is required to apply the + // filter to the newly added list. + list->setForceRefresh(true); + + list->setFilterSubString(mFilterSubString); + } } // Handle removed tabs. @@ -244,35 +262,9 @@ void LLOutfitsList::performAction(std::string action) void LLOutfitsList::setFilterSubString(const std::string& string) { - mFilterSubString = string; - - for (outfits_map_t::iterator - iter = mOutfitsMap.begin(), - iter_end = mOutfitsMap.end(); - iter != iter_end; ++iter) - { - LLAccordionCtrlTab* tab = iter->second; - if (tab) - { - LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*> (tab->getAccordionView()); - if (list) - { - list->setFilterSubString(mFilterSubString); - } + applyFilter(string); - if(!mFilterSubString.empty()) - { - //store accordion tab state when filter is not empty - tab->notifyChildren(LLSD().with("action","store_state")); - tab->setDisplayChildren(true); - } - else - { - //restore accordion state after all those accodrion tab manipulations - tab->notifyChildren(LLSD().with("action","restore_state")); - } - } - } + mFilterSubString = string; } ////////////////////////////////////////////////////////////////////////// @@ -350,4 +342,112 @@ void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUI mSelectedOutfitUUID = category_id; } +void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl) +{ + if (!ctrl || mFilterSubString.empty()) + return; + + for (outfits_map_t::iterator + iter = mOutfitsMap.begin(), + iter_end = mOutfitsMap.end(); + iter != iter_end; ++iter) + { + LLAccordionCtrlTab* tab = iter->second; + if (!tab) continue; + + LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView()); + if (list != ctrl) continue; + + std::string title = tab->getTitle(); + LLStringUtil::toUpper(title); + + std::string cur_filter = mFilterSubString; + LLStringUtil::toUpper(cur_filter); + + if (std::string::npos == title.find(cur_filter)) + { + // hide tab if its title doesn't pass filter + // and it has no visible items + tab->setVisible(list->size() != 0); + } + else + { + tab->setTitle(tab->getTitle(), cur_filter); + } + } +} + +void LLOutfitsList::applyFilter(const std::string& new_filter_substring) +{ + for (outfits_map_t::iterator + iter = mOutfitsMap.begin(), + iter_end = mOutfitsMap.end(); + iter != iter_end; ++iter) + { + LLAccordionCtrlTab* tab = iter->second; + if (!tab) continue; + + bool more_restrictive = mFilterSubString.size() < new_filter_substring.size() && !new_filter_substring.substr(0, mFilterSubString.size()).compare(mFilterSubString); + + // Restore tab visibility in case of less restrictive filter + // to compare it with updated string if it was previously hidden. + if (!more_restrictive) + { + tab->setVisible(TRUE); + } + + LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView()); + if (list) + { + list->setFilterSubString(new_filter_substring); + } + + if(mFilterSubString.empty() && !new_filter_substring.empty()) + { + //store accordion tab state when filter is not empty + tab->notifyChildren(LLSD().with("action","store_state")); + } + + if (!new_filter_substring.empty()) + { + std::string title = tab->getTitle(); + LLStringUtil::toUpper(title); + + std::string cur_filter = new_filter_substring; + LLStringUtil::toUpper(cur_filter); + + if (std::string::npos == title.find(cur_filter)) + { + // hide tab if its title doesn't pass filter + // and it has no visible items + tab->setVisible(list->size() != 0); + } + else + { + tab->setTitle(tab->getTitle(), cur_filter); + } + + if (tab->getVisible()) + { + // Open tab if it has passed the filter. + tab->setDisplayChildren(true); + } + else + { + // Set force refresh flag to refresh not visible list + // when some changes occur in it. + list->setForceRefresh(true); + } + } + else + { + // restore tab title when filter is empty + tab->setTitle(tab->getTitle()); + + //restore accordion state after all those accodrion tab manipulations + tab->notifyChildren(LLSD().with("action","restore_state")); + } + } +} + // EOF diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index d86cf5a703..8eaa39e6f1 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -94,6 +94,17 @@ private: */ void changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id); + /** + * Called upon list refresh event to update tab visibility depending on + * the results of applying filter to the title and list items of the tab. + */ + void onFilteredWearableItemsListRefresh(LLUICtrl* ctrl); + + /** + * Highlights filtered items and hides tabs which haven't passed filter. + */ + void applyFilter(const std::string& new_filter_substring); + LLInventoryCategoriesObserver* mCategoriesObserver; LLAccordionCtrl* mAccordion; diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index ddd41a1791..555248e31a 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -212,7 +212,6 @@ void LLPanelGroupGeneral::setupCtrls(LLPanel* panel_group) if (mInsignia) { mInsignia->setCommitCallback(onCommitAny, this); - mDefaultIconID = mInsignia->getImageAssetID(); } mFounderName = getChild<LLNameBox>("founder_name"); @@ -656,7 +655,7 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) } else { - mInsignia->setImageAssetID(mDefaultIconID); + mInsignia->setImageAssetName(mInsignia->getDefaultImageName()); } } @@ -846,16 +845,7 @@ void LLPanelGroupGeneral::reset() mInsignia->setEnabled(true); - LLPointer<LLUIImage> imagep = LLUI::getUIImage(mInsignia->getDefaultImageName()); - if(imagep) - { - LLViewerFetchedTexture* pTexture = dynamic_cast<LLViewerFetchedTexture*>(imagep->getImage().get()); - if(pTexture) - { - LLUUID id = pTexture->getID(); - mInsignia->setImageAssetID(id); - } - } + mInsignia->setImageAssetName(mInsignia->getDefaultImageName()); { std::string empty_str = ""; diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h index 6245018871..6f4fa994da 100644 --- a/indra/newview/llpanelgroupgeneral.h +++ b/indra/newview/llpanelgroupgeneral.h @@ -95,7 +95,6 @@ private: BOOL mChanged; BOOL mFirstUse; std::string mIncompleteMemberDataStr; - LLUUID mDefaultIconID; // Group information (include any updates in updateChanged) LLLineEditor *mGroupNameEditor; diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index a77ba0c69c..93fbecfd3f 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -118,8 +118,7 @@ LLPanelGroupRoles::LLPanelGroupRoles() mCurrentTab(NULL), mRequestedTab( NULL ), mSubTabContainer( NULL ), - mFirstUse( TRUE ), - mIgnoreTransition( FALSE ) + mFirstUse( TRUE ) { } @@ -153,8 +152,8 @@ BOOL LLPanelGroupRoles::postBuild() //subtabp->addObserver(this); } - // Add click callbacks to all the tabs. - mSubTabContainer->setCommitCallback(boost::bind(&LLPanelGroupRoles::handleClickSubTab, this)); + // Add click callbacks to tab switching. + mSubTabContainer->setValidateBeforeCommit(boost::bind(&LLPanelGroupRoles::handleSubTabSwitch, this, _1)); // Set the current tab to whatever is currently being shown. mCurrentTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel(); @@ -196,30 +195,20 @@ BOOL LLPanelGroupRoles::isVisibleByAgent(LLAgent* agentp) } -void LLPanelGroupRoles::handleClickSubTab() +bool LLPanelGroupRoles::handleSubTabSwitch(const LLSD& data) { - // If we are already handling a transition, - // ignore this. - if (mIgnoreTransition) - { - return; - } - - mRequestedTab = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel(); + std::string panel_name = data.asString(); + + LLPanelGroupTab* activating_tab = static_cast<LLPanelGroupTab*>(mSubTabContainer->getPanelByName(panel_name)); - // Make sure they aren't just clicking the same tab... - if (mRequestedTab == mCurrentTab) + if(activating_tab == mCurrentTab + || activating_tab == mRequestedTab) { - return; + return true; } - // Try to switch from the current panel to the panel the user selected. - attemptTransition(); -} - -BOOL LLPanelGroupRoles::attemptTransition() -{ - // Check if the current tab needs to be applied. + mRequestedTab = activating_tab; + std::string mesg; if (mCurrentTab && mCurrentTab->needsApply(mesg)) { @@ -235,16 +224,10 @@ BOOL LLPanelGroupRoles::attemptTransition() LLNotificationsUtil::add("PanelGroupApply", args, LLSD(), boost::bind(&LLPanelGroupRoles::handleNotifyCallback, this, _1, _2)); mHasModal = TRUE; - // We need to reselect the current tab, since it isn't finished. - if (mSubTabContainer) - { - mIgnoreTransition = TRUE; - mSubTabContainer->selectTabPanel( mCurrentTab ); - mIgnoreTransition = FALSE; - } + // Returning FALSE will block a close action from finishing until // we get a response back from the user. - return FALSE; + return false; } else { @@ -253,7 +236,7 @@ BOOL LLPanelGroupRoles::attemptTransition() { transitionToTab(); } - return TRUE; + return true; } } @@ -271,6 +254,7 @@ void LLPanelGroupRoles::transitionToTab() // This is now the current tab; mCurrentTab = mRequestedTab; mCurrentTab->activate(); + mRequestedTab = 0; } } @@ -278,6 +262,7 @@ bool LLPanelGroupRoles::handleNotifyCallback(const LLSD& notification, const LLS { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); mHasModal = FALSE; + LLPanelGroupTab* transition_tab = mRequestedTab; switch (option) { case 0: // "Apply Changes" @@ -297,26 +282,20 @@ bool LLPanelGroupRoles::handleNotifyCallback(const LLSD& notification, const LLS // Skip switching tabs. break; } - - // This panel's info successfully applied. - // Switch to the next panel. - // No break! Continue into 'Ignore Changes' which just switches tabs. - mIgnoreTransition = TRUE; - mSubTabContainer->selectTabPanel( mRequestedTab ); - mIgnoreTransition = FALSE; transitionToTab(); + mSubTabContainer->selectTabPanel( transition_tab ); + break; } case 1: // "Ignore Changes" // Switch to the requested panel without applying changes cancel(); - mIgnoreTransition = TRUE; - mSubTabContainer->selectTabPanel( mRequestedTab ); - mIgnoreTransition = FALSE; transitionToTab(); + mSubTabContainer->selectTabPanel( transition_tab ); break; case 2: // "Cancel" default: + mRequestedTab = NULL; // Do nothing. The user is canceling the action. break; } diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index 98cebe9882..a877402041 100644 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -65,7 +65,7 @@ public: virtual BOOL isVisibleByAgent(LLAgent* agentp); - void handleClickSubTab(); + bool handleSubTabSwitch(const LLSD& data); // Checks if the current tab needs to be applied, and tries to switch to the requested tab. BOOL attemptTransition(); @@ -93,7 +93,6 @@ protected: LLPanelGroupTab* mRequestedTab; LLTabContainer* mSubTabContainer; BOOL mFirstUse; - BOOL mIgnoreTransition; std::string mDefaultNeedsApplyMesg; std::string mWantApplyMesg; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 6634bc948d..4bf4f9eac1 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -993,10 +993,13 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const } else if("create_pick" == command_name) { - std::set<LLUUID> selection = mCurrentSelectedList->getRootFolder()->getSelectionList(); - if ( mCurrentSelectedList && !selection.empty() ) + if (mCurrentSelectedList) { - return ( 1 == selection.size() && !LLAgentPicksInfo::getInstance()->isPickLimitReached() ); + std::set<LLUUID> selection = mCurrentSelectedList->getRootFolder()->getSelectionList(); + if (!selection.empty()) + { + return ( 1 == selection.size() && !LLAgentPicksInfo::getInstance()->isPickLimitReached() ); + } } return false; } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index c04be85174..44832ac496 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -169,14 +169,48 @@ protected: S32 mBaseOutfitLastVersion; }; +class LLCOFDragAndDropObserver : public LLInventoryAddItemByAssetObserver +{ +public: + LLCOFDragAndDropObserver(LLInventoryModel* model); + + virtual ~LLCOFDragAndDropObserver(); + + virtual void done(); + +private: + LLInventoryModel* mModel; +}; + +inline LLCOFDragAndDropObserver::LLCOFDragAndDropObserver(LLInventoryModel* model): + mModel(model) +{ + if (model != NULL) + { + model->addObserver(this); + } +} + +inline LLCOFDragAndDropObserver::~LLCOFDragAndDropObserver() +{ + if (mModel != NULL && mModel->containsObserver(this)) + { + mModel->removeObserver(this); + } +} +void LLCOFDragAndDropObserver::done() +{ + LLAppearanceMgr::instance().updateAppearanceFromCOF(); +} LLPanelOutfitEdit::LLPanelOutfitEdit() : LLPanel(), mSearchFilter(NULL), mCOFWearables(NULL), mInventoryItemsPanel(NULL), - mCOFObserver(NULL) + mCOFObserver(NULL), + mCOFDragAndDropObserver(NULL) { mSavedFolderState = new LLSaveFolderState(); mSavedFolderState->setApply(FALSE); @@ -197,6 +231,7 @@ LLPanelOutfitEdit::~LLPanelOutfitEdit() delete mSavedFolderState; delete mCOFObserver; + delete mCOFDragAndDropObserver; } BOOL LLPanelOutfitEdit::postBuild() @@ -234,6 +269,8 @@ BOOL LLPanelOutfitEdit::postBuild() mInventoryItemsPanel->setSelectCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this, _1, _2)); mInventoryItemsPanel->getRootFolder()->setReshapeCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this, _1, _2)); + mCOFDragAndDropObserver = new LLCOFDragAndDropObserver(mInventoryItemsPanel->getModel()); + LLComboBox* type_filter = getChild<LLComboBox>("filter_wearables_combobox"); type_filter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onTypeFilterChanged, this, _1)); type_filter->removeall(); @@ -522,6 +559,56 @@ void LLPanelOutfitEdit::update() updateVerbs(); } +BOOL LLPanelOutfitEdit::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + if (cargo_data == NULL) + { + llwarns << "cargo_data is NULL" << llendl; + return TRUE; + } + + switch (cargo_type) + { + case DAD_BODYPART: + case DAD_CLOTHING: + case DAD_OBJECT: + case DAD_LINK: + *accept = ACCEPT_YES_MULTI; + break; + default: + *accept = ACCEPT_NO; + } + + if (drop) + { + LLInventoryItem* item = static_cast<LLInventoryItem*>(cargo_data); + + if (LLAssetType::lookupIsAssetIDKnowable(item->getType())) + { + mCOFDragAndDropObserver->watchAsset(item->getAssetUUID()); + + /* + * Adding request to wear item. If the item is a link, then getLinkedUUID() will + * return the ID of the linked item. Otherwise it will return the item's ID. The + * second argument is used to delay the appearance update until all dragged items + * are added to optimize user experience. + */ + LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), false); + } + else + { + // if asset id is not available for the item we must wear it immediately (attachments only) + LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), true); + } + } + + return TRUE; +} + void LLPanelOutfitEdit::displayCurrentOutfit() { if (!getVisible()) diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index cb8283fca3..953a70785c 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -50,6 +50,7 @@ class LLCOFWearables; class LLTextBox; class LLInventoryCategory; class LLCOFObserver; +class LLCOFDragAndDropObserver; class LLInventoryPanel; class LLSaveFolderState; class LLFolderViewItem; @@ -114,6 +115,12 @@ public: */ bool switchPanels(LLPanel* switch_from_panel, LLPanel* switch_to_panel); + virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + private: @@ -134,6 +141,8 @@ private: LLPanel* mWearableItemsPanel; LLCOFObserver* mCOFObserver; + LLCOFDragAndDropObserver* mCOFDragAndDropObserver; + std::vector<LLLookItemType> mLookItemTypes; LLCOFWearables* mCOFWearables; diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 660615df5a..ea75c16c56 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -134,11 +134,6 @@ void LLPanelOutfitsInventory::onOpen(const LLSD& key) void LLPanelOutfitsInventory::updateVerbs() { - if (mParent) - { - mParent->updateVerbs(); - } - if (mListCommands) { updateListCommands(); diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index e8b6c6bfe5..4dd03e04a9 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -38,7 +38,7 @@ #include "llsidetray.h" #include "llworldmap.h" #include "llteleporthistorystorage.h" -#include "lltextutil.h" +#include "lluitextutil.h" #include "llaccordionctrl.h" #include "llaccordionctrltab.h" diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index feaf7335c0..1117ae05d7 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -37,6 +37,8 @@ #include "llavataractions.h" #include "llagent.h" +#include "llimview.h" +#include "llnotificationsutil.h" #include "llparticipantlist.h" #include "llspeakers.h" #include "llviewercontrol.h" @@ -653,6 +655,7 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1); main_menu->setItemVisible("SortByName", is_sort_visible); main_menu->setItemVisible("SortByRecentSpeakers", is_sort_visible); + main_menu->setItemVisible("Moderator Options Separator", isGroupModerator()); main_menu->setItemVisible("Moderator Options", isGroupModerator()); main_menu->setItemVisible("View Icons Separator", mParent.mAvatarListToggleIconsConnection.connected()); main_menu->setItemVisible("View Icons", mParent.mAvatarListToggleIconsConnection.connected()); @@ -809,10 +812,43 @@ void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(co LLIMSpeakerMgr* mgr = dynamic_cast<LLIMSpeakerMgr*>(mParent.mSpeakerMgr); if (mgr) { + if (!unmute) + { + LLSD payload; + payload["session_id"] = mgr->getSessionID(); + payload["excluded_avatar_id"] = excluded_avatar_id; + LLNotificationsUtil::add("ConfirmMuteAll", LLSD(), payload, confirmMuteAllCallback); + return; + } + mgr->moderateVoiceOtherParticipants(excluded_avatar_id, unmute); } } +// static +void LLParticipantList::LLParticipantListMenu::confirmMuteAllCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 1) + { + return; + } + + const LLSD& payload = notification["payload"]; + const LLUUID& session_id = payload["session_id"]; + const LLUUID& excluded_avatar_id = payload["excluded_avatar_id"]; + + LLIMSpeakerMgr * speaker_manager = dynamic_cast<LLIMSpeakerMgr*> ( + LLIMModel::getInstance()->getSpeakerManager(session_id)); + if (speaker_manager) + { + speaker_manager->moderateVoiceOtherParticipants(excluded_avatar_id, false); + } + + return; +} + + bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata) { std::string item = userdata.asString(); diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index bbef8baaac..abaf503868 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -216,6 +216,8 @@ class LLParticipantList * @see moderateVoiceParticipant() */ void moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute); + + static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response); }; /** diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 0086c6aec4..658a7b52e3 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -118,9 +118,6 @@ BOOL LLSidepanelAppearance::postBuild() childSetAction("edit_outfit_btn", boost::bind(&LLSidepanelAppearance::onEditOutfitButtonClicked, this)); - mEditBtn = getChild<LLButton>("edit_btn"); - mEditBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditButtonClicked, this)); - mNewOutfitBtn = getChild<LLButton>("newlook_btn"); mNewOutfitBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onNewOutfitButtonClicked, this)); mNewOutfitBtn->setEnabled(false); @@ -172,24 +169,24 @@ void LLSidepanelAppearance::onOpen(const LLSD& key) { fetchInventory(); refreshCurrentOutfitName(); - updateVerbs(); if (mPanelOutfitsInventory) { mPanelOutfitsInventory->onOpen(key); } - if(key.size() == 0) + if (!key.has("type")) return; - - toggleOutfitEditPanel(TRUE); - updateVerbs(); - - mLookInfoType = key["type"].asString(); - if (mLookInfoType == "edit_outfit") + // Switch to the requested panel. + std::string type = key["type"].asString(); + if (type == "my_outfits") { - mOutfitEdit->displayCurrentOutfit(); + showOutfitsInventoryPanel(); + } + else if (type == "edit_outfit") + { + showOutfitEditPanel(/*update = */ true); } } @@ -233,6 +230,7 @@ void LLSidepanelAppearance::onOpenOutfitButtonClicked() } } +// *TODO: obsolete? void LLSidepanelAppearance::onEditAppearanceButtonClicked() { if (gAgentWearables.areWearablesLoaded()) @@ -248,19 +246,6 @@ void LLSidepanelAppearance::onEditOutfitButtonClicked() LLSideTray::getInstance()->showPanel("sidepanel_appearance", key); } -void LLSidepanelAppearance::onEditButtonClicked() -{ - toggleOutfitEditPanel(FALSE); - toggleWearableEditPanel(TRUE, NULL); - /*if (mOutfitEdit->getVisible()) - { - } - else - { - mPanelOutfitsInventory->onEdit(); - }*/ -} - void LLSidepanelAppearance::onNewOutfitButtonClicked() { if (!mOutfitEdit->getVisible()) @@ -271,33 +256,27 @@ void LLSidepanelAppearance::onNewOutfitButtonClicked() void LLSidepanelAppearance::onEditWearBackClicked() { - mEditWearable->saveChanges(); - toggleWearableEditPanel(FALSE, NULL); - toggleOutfitEditPanel(TRUE); + showOutfitEditPanel(/* update = */ false); } void LLSidepanelAppearance::showOutfitsInventoryPanel() { - mOutfitEdit->setVisible(FALSE); - - mPanelOutfitsInventory->setVisible(TRUE); - - mFilterEditor->setVisible(TRUE); - mEditBtn->setVisible(TRUE); - mNewOutfitBtn->setVisible(TRUE); - mCurrOutfitPanel->setVisible(TRUE); + toggleWearableEditPanel(FALSE); + toggleOutfitEditPanel(FALSE); } -void LLSidepanelAppearance::showOutfitEditPanel() +void LLSidepanelAppearance::showOutfitEditPanel(bool update) { - mOutfitEdit->setVisible(TRUE); - - mPanelOutfitsInventory->setVisible(FALSE); + if (!mOutfitEdit) + return; + + toggleWearableEditPanel(FALSE); + toggleOutfitEditPanel(TRUE); - mFilterEditor->setVisible(FALSE); - mEditBtn->setVisible(FALSE); - mNewOutfitBtn->setVisible(FALSE); - mCurrOutfitPanel->setVisible(FALSE); + if (update) + { + mOutfitEdit->displayCurrentOutfit(); + } } void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible) @@ -305,16 +284,27 @@ void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible) if (!mOutfitEdit) return; + if (mOutfitEdit->getVisible() == visible) + { + // visibility isn't changing, hence nothing to do + return; + } + mOutfitEdit->setVisible(visible); if (mPanelOutfitsInventory) mPanelOutfitsInventory->setVisible(!visible); mFilterEditor->setVisible(!visible); - mEditBtn->setVisible(!visible); mNewOutfitBtn->setVisible(!visible); mCurrOutfitPanel->setVisible(!visible); } void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *wearable) { + if (mEditWearable->getVisible() == visible) + { + // visibility isn't changing, hence nothing to do + return; + } + if (!wearable) { wearable = gAgentWearables.getWearable(LLWearableType::WT_SHAPE, 0); @@ -324,6 +314,13 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we return; } + // Save changes if closing. + if (!visible) + { + mEditWearable->saveChanges(); + } + + // Toggle panel visibility. mCurrOutfitPanel->setVisible(!visible); mEditWearable->setVisible(visible); @@ -332,21 +329,6 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we mPanelOutfitsInventory->setVisible(!visible); } -void LLSidepanelAppearance::updateVerbs() -{ - bool is_look_info_visible = mOutfitEdit->getVisible(); - - if (mPanelOutfitsInventory && !is_look_info_visible) - { -// const bool is_correct_type = (mPanelOutfitsInventory->getCorrectListenerForAction() != NULL); -// mEditBtn->setEnabled(is_correct_type); - } - else - { - mEditBtn->setEnabled(FALSE); - } -} - void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name) { // Set current outfit status (wearing/unsaved). diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 2900831099..a919b07ed6 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -60,11 +60,10 @@ public: void fetchInventory(); void inventoryFetched(); - void updateVerbs(); void onNewOutfitButtonClicked(); void showOutfitsInventoryPanel(); - void showOutfitEditPanel(); + void showOutfitEditPanel(bool update); void setWearablesLoading(bool val); private: @@ -73,12 +72,11 @@ private: void onOpenOutfitButtonClicked(); void onEditAppearanceButtonClicked(); void onEditOutfitButtonClicked(); - void onEditButtonClicked(); void onEditWearBackClicked(); //@deprecated use showXXX() methods instead void toggleOutfitEditPanel(BOOL visible); - void toggleWearableEditPanel(BOOL visible, LLWearable* wearable); + void toggleWearableEditPanel(BOOL visible, LLWearable* wearable = NULL); LLFilterEditor* mFilterEditor; LLPanelOutfitsInventory* mPanelOutfitsInventory; @@ -87,7 +85,6 @@ private: LLButton* mOpenOutfitBtn; LLButton* mEditAppearanceBtn; - LLButton* mEditBtn; LLButton* mNewOutfitBtn; LLPanel* mCurrOutfitPanel; @@ -103,10 +100,6 @@ private: // Search string for filtering landmarks and teleport // history locations std::string mFilterSubString; - - // Information type currently shown in Look Information panel - std::string mLookInfoType; - }; #endif //LL_LLSIDEPANELAPPEARANCE_H diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index 140a9c818a..e8fdee9430 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -94,7 +94,7 @@ public: * if no such tab - return NULL, otherwise a pointer to the panel * Pass params as array, or they may be overwritten(example - params["name"]="nearby") */ - LLPanel* showPanel (const std::string& panel_name, const LLSD& params); + LLPanel* showPanel (const std::string& panel_name, const LLSD& params = LLSD()); /** * Toggling Side Tray tab which contains "sub_panel" child of "panel_name" panel. @@ -102,7 +102,7 @@ public: * otherwise Side Tray is collapsed. * params are passed to "panel_name" panel onOpen(). */ - void togglePanel (LLPanel* &sub_panel, const std::string& panel_name, const LLSD& params); + void togglePanel (LLPanel* &sub_panel, const std::string& panel_name, const LLSD& params = LLSD()); /* * get the panel (don't show it or do anything else with it) diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 82fa672342..337627cc79 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -237,6 +237,7 @@ BOOL LLTexLayerSetBuffer::render() { if (mTexLayerSet->isVisible()) { + mTexLayerSet->getAvatar()->bakedTextureUpload(mTexLayerSet->getBakedTexIndex(), FALSE); // FALSE for start of upload, TRUE for finish. readBackAndUpload(); } else diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index a1b3c8dabd..9aebc264a2 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -1137,6 +1137,20 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op) } } +void LLTextureCtrl::setImageAssetName(const std::string& name) +{ + LLPointer<LLUIImage> imagep = LLUI::getUIImage(name); + if(imagep) + { + LLViewerFetchedTexture* pTexture = dynamic_cast<LLViewerFetchedTexture*>(imagep->getImage().get()); + if(pTexture) + { + LLUUID id = pTexture->getID(); + setImageAssetID(id); + } + } +} + void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id ) { if( mImageAssetID != asset_id ) @@ -1248,25 +1262,52 @@ void LLTextureCtrl::draw() mTentativeLabel->setVisible( !mTexturep.isNull() && getTentative() ); - // Show "Loading..." string on the top left corner while this texture is loading. // Using the discard level, do not show the string if the texture is almost but not // fully loaded. - if ( mTexturep.notNull() && - (!mTexturep->isFullyLoaded()) && - (mShowLoadingPlaceholder == TRUE) && - (mTexturep->getDiscardLevel() != 1) && - (mTexturep->getDiscardLevel() != 0)) + if (mTexturep.notNull() && + (!mTexturep->isFullyLoaded()) && + (mShowLoadingPlaceholder == TRUE)) { + U32 v_offset = 25; LLFontGL* font = LLFontGL::getFontSansSerif(); - font->renderUTF8( - mLoadingPlaceholderString, 0, - llfloor(interior.mLeft+3), - llfloor(interior.mTop-25), - LLColor4::white, - LLFontGL::LEFT, - LLFontGL::BASELINE, - LLFontGL::DROP_SHADOW); + + // Don't show as loaded if the texture is almost fully loaded (i.e. discard1) unless god + if ((mTexturep->getDiscardLevel() > 1) || gAgent.isGodlike()) + { + font->renderUTF8( + mLoadingPlaceholderString, + 0, + llfloor(interior.mLeft+3), + llfloor(interior.mTop-v_offset), + LLColor4::white, + LLFontGL::LEFT, + LLFontGL::BASELINE, + LLFontGL::DROP_SHADOW); + } + + // Show more detailed information if this agent is god. + if (gAgent.isGodlike()) + { + LLFontGL* font = LLFontGL::getFontSansSerif(); + std::string tdesc; + // Show what % the texture has loaded (0 to 100%, 100 is highest), and what level of detail (5 to 0, 0 is best). + + v_offset += 12; + tdesc = llformat(" PK : %d%%", U32(mTexturep->getDownloadProgress()*100.0)); + font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset), + LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); + + v_offset += 12; + tdesc = llformat(" LVL: %d", mTexturep->getDiscardLevel()); + font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset), + LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); + + v_offset += 12; + tdesc = llformat(" ID : %s...", (mImageAssetID.asString().substr(0,10)).c_str()); + font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset), + LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); + } } LLUICtrl::draw(); diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 837f837430..bcd0a083f2 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -128,7 +128,7 @@ public: virtual void clear(); // Takes a UUID, wraps get/setImageAssetID - virtual void setValue(const LLSD& value ); + virtual void setValue(const LLSD& value); virtual LLSD getValue() const; // LLTextureCtrl interface @@ -142,6 +142,8 @@ public: const LLUUID& getImageItemID() { return mImageItemID; } + virtual void setImageAssetName(const std::string& name); + void setImageAssetID(const LLUUID &image_asset_id); const LLUUID& getImageAssetID() const { return mImageAssetID; } diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index a31c3a0f1b..9efa6c4108 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -151,8 +151,9 @@ bool LLURLDispatcherImpl::dispatchApp(const LLSLURL& slurl, bool trusted_browser) { llinfos << "cmd: " << slurl.getAppCmd() << " path: " << slurl.getAppPath() << " query: " << slurl.getAppQuery() << llendl; + const LLSD& query_map = LLURI::queryMap(slurl.getAppQuery()); bool handled = LLCommandDispatcher::dispatch( - slurl.getAppCmd(), slurl.getAppPath(), slurl.getAppQuery(), web, trusted_browser); + slurl.getAppCmd(), slurl.getAppPath(), query_map, web, trusted_browser); // alert if we didn't handle this secondlife:///app/ SLURL // (but still return true because it is a valid app SLURL) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 49748c59e8..a2331bd69a 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -95,6 +95,41 @@ public: mInventoryItemsDict["New Script"] = LLTrans::getString("New Script"); mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder"); mInventoryItemsDict["Contents"] = LLTrans::getString("Contents"); + + mInventoryItemsDict["Gesture"] = LLTrans::getString("Gesture"); + mInventoryItemsDict["Male Gestures"] = LLTrans::getString("Male Gestures"); + mInventoryItemsDict["Female Gestures"] = LLTrans::getString("Female Gestures"); + mInventoryItemsDict["Other Gestures"] = LLTrans::getString("Other Gestures"); + mInventoryItemsDict["Speech Gestures"] = LLTrans::getString("Speech Gestures"); + + //predefined gestures + + //male + mInventoryItemsDict["Male - Excuse me"] = LLTrans::getString("Male - Excuse me"); + mInventoryItemsDict["Male - Get lost"] = LLTrans::getString("Male - Get lost"); + mInventoryItemsDict["Male - Blow kiss"] = LLTrans::getString("Male - Blow kiss"); + mInventoryItemsDict["Male - Boo"] = LLTrans::getString("Male - Boo"); + mInventoryItemsDict["Male - Bored"] = LLTrans::getString("Male - Bored"); + mInventoryItemsDict["Male - Hey"] = LLTrans::getString("Male - Hey"); + mInventoryItemsDict["Male - Laugh"] = LLTrans::getString("Male - Laugh"); + mInventoryItemsDict["Male - Repulsed"] = LLTrans::getString("Male - Repulsed"); + mInventoryItemsDict["Male - Shrug"] = LLTrans::getString("Male - Shrug"); + mInventoryItemsDict["Male - Stick tougue out"] = LLTrans::getString("Male - Stick tougue out"); + mInventoryItemsDict["Male - Wow"] = LLTrans::getString("Male - Wow"); + + //female + mInventoryItemsDict["FeMale - Excuse me"] = LLTrans::getString("FeMale - Excuse me"); + mInventoryItemsDict["FeMale - Get lost"] = LLTrans::getString("FeMale - Get lost"); + mInventoryItemsDict["FeMale - Blow kiss"] = LLTrans::getString("FeMale - Blow kiss"); + mInventoryItemsDict["FeMale - Boo"] = LLTrans::getString("FeMale - Boo"); + mInventoryItemsDict["Female - Bored"] = LLTrans::getString("Female - Bored"); + mInventoryItemsDict["Female - Hey"] = LLTrans::getString("Female - Hey"); + mInventoryItemsDict["Female - Laugh"] = LLTrans::getString("Female - Laugh"); + mInventoryItemsDict["Female - Repulsed"] = LLTrans::getString("Female - Repulsed"); + mInventoryItemsDict["Female - Shrug"] = LLTrans::getString("Female - Shrug"); + mInventoryItemsDict["Female - Stick tougue out"]= LLTrans::getString("Female - Stick tougue out"); + mInventoryItemsDict["Female - Wow"] = LLTrans::getString("Female - Wow"); + } }; @@ -1653,6 +1688,20 @@ bool LLViewerInventoryItem::checkPermissionsSet(PermissionMask mask) const return ((curr_mask & mask) == mask); } +PermissionMask LLViewerInventoryItem::getPermissionMask() const +{ + const LLPermissions& permissions = getPermissions(); + + BOOL copy = permissions.allowCopyBy(gAgent.getID()); + BOOL mod = permissions.allowModifyBy(gAgent.getID()); + BOOL xfer = permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID()); + PermissionMask perm_mask = 0; + if (copy) perm_mask |= PERM_COPY; + if (mod) perm_mask |= PERM_MODIFY; + if (xfer) perm_mask |= PERM_TRANSFER; + return perm_mask; +} + //---------- void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name) diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index f0dc7bcb67..8ab7c9710d 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -159,6 +159,7 @@ public: // Checks the items permissions (for owner, group, or everyone) and returns true if all mask bits are set. bool checkPermissionsSet(PermissionMask mask) const; + PermissionMask getPermissionMask() const; // callback void onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name); diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index c1e851350b..02e450b223 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -215,6 +215,8 @@ void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal, // We need the aspect ratio, and the 3 components of the bbox as height, width, and depth. F32 aspect_ratio = getBBoxAspectRatio(bbox, normal, &height, &width, &depth); F32 camera_aspect = LLViewerCamera::getInstance()->getAspect(); + + lldebugs << "normal = " << normal << ", aspect_ratio = " << aspect_ratio << ", camera_aspect = " << camera_aspect << llendl; // We will normally use the side of the volume aligned with the short side of the screen (i.e. the height for // a screen in a landscape aspect ratio), however there is an edge case where the aspect ratio of the object is @@ -231,11 +233,15 @@ void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal, { angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect()); distance = width * 0.5 * padding_factor / tan(angle_of_view * 0.5f ); + + lldebugs << "using width (" << width << "), angle_of_view = " << angle_of_view << ", distance = " << distance << llendl; } else { angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getView()); distance = height * 0.5 * padding_factor / tan(angle_of_view * 0.5f ); + + lldebugs << "using height (" << height << "), angle_of_view = " << angle_of_view << ", distance = " << distance << llendl; } distance += depth * 0.5; @@ -440,40 +446,38 @@ F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& LLVector3 bbox_max = bbox.getExtentLocal(); F32 dot1 = 0.f; F32 dot2 = 0.f; + + lldebugs << "bounding box local size = " << bbox_max << ", local_normal = " << local_normal << llendl; // The largest component of the localized normal vector is the depth component // meaning that the other two are the legs of the rectangle. local_normal.abs(); - if(local_normal.mV[VX] > local_normal.mV[VY]) + + // Using temporary variables for these makes the logic a bit more readable. + bool XgtY = (local_normal.mV[VX] > local_normal.mV[VY]); + bool XgtZ = (local_normal.mV[VX] > local_normal.mV[VZ]); + bool YgtZ = (local_normal.mV[VY] > local_normal.mV[VZ]); + + if(XgtY && XgtZ) { - if(local_normal.mV[VX] > local_normal.mV[VZ]) - { - // Use the y and z comps - comp1.mV[VY] = bbox_max.mV[VY]; - comp2.mV[VZ] = bbox_max.mV[VZ]; - *depth = bbox_max.mV[VX]; - } - else - { - // Use the x and y comps - comp1.mV[VY] = bbox_max.mV[VY]; - comp2.mV[VZ] = bbox_max.mV[VZ]; - *depth = bbox_max.mV[VZ]; - } + lldebugs << "x component of normal is longest, using y and z" << llendl; + comp1.mV[VY] = bbox_max.mV[VY]; + comp2.mV[VZ] = bbox_max.mV[VZ]; + *depth = bbox_max.mV[VX]; } - else if(local_normal.mV[VY] > local_normal.mV[VZ]) + else if(!XgtY && YgtZ) { - // Use the x and z comps + lldebugs << "y component of normal is longest, using x and z" << llendl; comp1.mV[VX] = bbox_max.mV[VX]; comp2.mV[VZ] = bbox_max.mV[VZ]; *depth = bbox_max.mV[VY]; } else { - // Use the x and y comps - comp1.mV[VY] = bbox_max.mV[VY]; - comp2.mV[VZ] = bbox_max.mV[VZ]; - *depth = bbox_max.mV[VX]; + lldebugs << "z component of normal is longest, using x and y" << llendl; + comp1.mV[VX] = bbox_max.mV[VX]; + comp2.mV[VY] = bbox_max.mV[VY]; + *depth = bbox_max.mV[VZ]; } // The height is the vector closest to vertical in the bbox coordinate space (highest dot product value) @@ -483,12 +487,20 @@ F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& { *height = comp1.length(); *width = comp2.length(); + + lldebugs << "comp1 = " << comp1 << ", height = " << *height << llendl; + lldebugs << "comp2 = " << comp2 << ", width = " << *width << llendl; } else { *height = comp2.length(); *width = comp1.length(); + + lldebugs << "comp2 = " << comp2 << ", height = " << *height << llendl; + lldebugs << "comp1 = " << comp1 << ", width = " << *width << llendl; } + + lldebugs << "returning " << (*width / *height) << llendl; // Return the aspect ratio. return *width / *height; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 42428bab03..c245650d51 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -5597,10 +5597,7 @@ void handle_viewer_disable_message_log(void*) void handle_customize_avatar() { - if (gAgentWearables.areWearablesLoaded()) - { - gAgentCamera.changeCameraToCustomizeAvatar(); - } + LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "my_outfits")); } void handle_report_abuse() diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 4b7c7f297b..fb87e2d3b9 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -774,11 +774,11 @@ private: * We can't create it each time items are moved because "drop" event is sent separately for each * element even while multi-dragging. We have to have the only instance of the observer. See EXT-4347. */ -class LLViewerInventoryMoveFromWorldObserver : public LLInventoryMoveFromWorldObserver +class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetObserver { public: LLViewerInventoryMoveFromWorldObserver() - : LLInventoryMoveFromWorldObserver() + : LLInventoryAddItemByAssetObserver() , mActivePanel(NULL) { @@ -6474,18 +6474,3 @@ void LLOfferInfo::forceResponse(InventoryOfferResponse response) LLNotifications::instance().forceResponse(params, response); } -static bool confirm_leave_call_callback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - const LLSD& payload = notification["payload"]; - LLUUID session_id = payload["session_id"]; - - LLFloater* im_floater = LLFloaterReg::findInstance("impanel", session_id); - if (option == 0 && im_floater != NULL) - { - im_floater->closeFloater(); - } - - return false; -} -static LLNotificationFunctorRegistration confirm_leave_call_cb("ConfirmLeaveCall", confirm_leave_call_callback); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 2ec8ced543..f95017b658 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -667,6 +667,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mTexEyeColor( NULL ), mNeedsSkin(FALSE), mUpdatePeriod(1), + mFullyLoaded(FALSE), + mPreviousFullyLoaded(FALSE), mFullyLoadedInitialized(FALSE), mSupportsAlphaLayers(FALSE) { @@ -746,8 +748,10 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mOohMorph = NULL; mAahMorph = NULL; - mCurrentGesticulationLevel = 0; + mCurrentGesticulationLevel = 0; + mRuthTimer.reset(); + mRuthDebugTimer.reset(); } //------------------------------------------------------------------------ @@ -755,6 +759,25 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, //------------------------------------------------------------------------ LLVOAvatar::~LLVOAvatar() { + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + if (!mFullyLoaded) + { + llinfos << "AVATARREZTIME: Avatar '" << getFullname() << " left after " << (U32)mRuthDebugTimer.getElapsedTimeF32() << " seconds as cloud." << llendl; + LLSD args; + args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); + args["NAME"] = getFullname(); + LLNotificationsUtil::add("AvatarRezLeftCloudNotification",args); + } + else + { + llinfos << "AVATARREZTIME: Avatar '" << getFullname() << " left." << llendl; + LLSD args; + args["NAME"] = getFullname(); + LLNotificationsUtil::add("AvatarRezLeftNotification",args); + } + + } lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl; mRoot.removeAllChildren(); @@ -1269,6 +1292,7 @@ void LLVOAvatar::initInstance(void) //VTPause(); // VTune mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) ); + } const LLVector3 LLVOAvatar::getRenderPosition() const @@ -2076,9 +2100,22 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, LLMemType mt(LLMemType::MTYPE_AVATAR); LLVector3 old_vel = getVelocity(); + const BOOL has_name = !getNVPair("FirstName"); + // Do base class updates... U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); + // Print out arrival information once we have name of avatar. + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + if (has_name && getNVPair("FirstName")) + { + LLSD args; + args["NAME"] = getFullname(); + LLNotificationsUtil::add("AvatarRezArrivedNotification",args); + llinfos << "AVATARREZTIME: Avatar '" << getFullname() << "' arrived." << llendl; + } + } if(retval & LLViewerObject::INVALID_UPDATE) { if (isSelf()) @@ -5863,20 +5900,28 @@ void LLVOAvatar::updateRuthTimer(bool loading) if (mPreviousFullyLoaded) { mRuthTimer.reset(); + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + llinfos << "AVATARREZTIME: Avatar '" << getFullname() << "' became cloud." << llendl; + LLSD args; + args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); + args["NAME"] = getFullname(); + LLNotificationsUtil::add("AvatarRezCloudNotification",args); + } mRuthDebugTimer.reset(); } const F32 LOADING_TIMEOUT = 120.f; if (mRuthTimer.getElapsedTimeF32() > LOADING_TIMEOUT) { - /* + llinfos << "Ruth Timer timeout: Missing texture data for '" << getFullname() << "' " << "( Params loaded : " << !visualParamWeightsAreDefault() << " ) " << "( Lower : " << isTextureDefined(TEX_LOWER_BAKED) << " ) " << "( Upper : " << isTextureDefined(TEX_UPPER_BAKED) << " ) " << "( Head : " << isTextureDefined(TEX_HEAD_BAKED) << " )." << llendl; - */ + LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID()); mRuthTimer.reset(); } @@ -5896,7 +5941,7 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) { if (!mPreviousFullyLoaded && !loading && mFullyLoaded) { - llinfos << "Avatar '" << getFullname() << "' resolved in " << mRuthDebugTimer.getElapsedTimeF32() << " seconds." << llendl; + llinfos << "AVATARREZTIME: Avatar '" << getFullname() << "' resolved in " << (U32)mRuthDebugTimer.getElapsedTimeF32() << " seconds." << llendl; LLSD args; args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); args["NAME"] = getFullname(); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index dec2e7efdf..e8f42178a1 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -103,15 +103,7 @@ struct LocalTextureData //----------------------------------------------------------------------------- // Callback data //----------------------------------------------------------------------------- -struct LLAvatarTexData -{ - LLAvatarTexData(const LLUUID& id, ETextureIndex index) : - mAvatarID(id), - mIndex(index) - {} - LLUUID mAvatarID; - ETextureIndex mIndex; -}; + /** ** @@ -156,6 +148,23 @@ void LLVOAvatarSelf::initInstance() // adds attachment points to mScreen among other things LLVOAvatar::initInstance(); + llinfos << "Self avatar object created. Starting timer." << llendl; + mSelfLoadTimer.reset(); + // clear all times to -1 for debugging + for (U32 i =0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i) + { + for (U32 j = 0; j <= MAX_DISCARD_LEVEL; ++j) + { + mTextureLoadTimes[i][j] = -1.0f; + } + } + + for (U32 i =0; i < LLVOAvatarDefines::BAKED_NUM_INDICES; ++i) + { + mBakedTextureTimes[i][0] = -1.0f; + mBakedTextureTimes[i][1] = -1.0f; + } + status &= buildMenus(); if (!status) { @@ -1117,12 +1126,12 @@ U32 LLVOAvatarSelf::getNumWearables(LLVOAvatarDefines::ETextureIndex i) const // virtual void LLVOAvatarSelf::localTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src_raw, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) { - //llinfos << "onLocalTextureLoaded: " << src_vi->getID() << llendl; const LLUUID& src_id = src_vi->getID(); LLAvatarTexData *data = (LLAvatarTexData *)userdata; ETextureIndex index = data->mIndex; if (!isIndexLocalTexture(index)) return; + LLLocalTextureObject *local_tex_obj = getLocalTextureObject(index, 0); // fix for EXT-268. Preventing using of NULL pointer @@ -1748,6 +1757,33 @@ BOOL LLVOAvatarSelf::getIsCloud() return FALSE; } +/*static*/ +void LLVOAvatarSelf::onTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) +{ + gAgentAvatarp->timingLocalTexLoaded(success, src_vi, src, aux_src, discard_level, final, userdata); +} + +void LLVOAvatarSelf::timingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) +{ + LLAvatarTexData *data = (LLAvatarTexData *)userdata; + ETextureIndex index = data->mIndex; + + if (discard_level >=0 && discard_level <= MAX_DISCARD_LEVEL) // ignore discard level -1, as it means we have no data. + { + mTextureLoadTimes[(U32)index][(U32)discard_level] = mSelfLoadTimer.getElapsedTimeF32(); + } + delete data; +} + +void LLVOAvatarSelf::bakedTextureUpload(EBakedTextureIndex index, BOOL finished) +{ + U32 done = 0; + if (finished) + { + done = 1; + } + mBakedTextureTimes[index][done] = mSelfLoadTimer.getElapsedTimeF32(); +} const LLUUID& LLVOAvatarSelf::grabLocalTexture(ETextureIndex type, U32 index) const { @@ -1907,6 +1943,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(te); if (texture_dict->mIsBakedTexture) { + bakedTextureUpload(texture_dict->mBakedTextureIndex, TRUE); // FALSE for start of upload, TRUE for finish. llinfos << "New baked texture: " << texture_dict->mName << " UUID: " << uuid <<llendl; } else @@ -1919,6 +1956,42 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) if (!hasPendingBakedUploads()) { gAgent.sendAgentSetAppearance(); + F32 final_time = mSelfLoadTimer.getElapsedTimeF32(); + llinfos << "AVATARREZTIME: Myself rez stats:" << llendl; + llinfos << "\t Time from avatar creation to load wearables: " << (S32)mTimeWearablesLoaded << llendl; + llinfos << "\t Time from avatar creation to de-cloud: " << (S32)mTimeAvatarVisible << llendl; + llinfos << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << llendl; + llinfos << "\t Load time for each texture: " << llendl; + for (U32 i = 0; i < LLVOAvatarDefines::TEX_NUM_INDICES; ++i) + { + std::stringstream out; + out << "\t\t (" << i << ") "; + U32 j=0; + for (j=0; j <= MAX_DISCARD_LEVEL; j++) + { + out << "\t"; + S32 load_time = (S32)mTextureLoadTimes[i][j]; + if (load_time == -1) + { + out << "*"; + if (j == 0) + break; + } + else + { + out << load_time; + } + } + + // Don't print out non-existent textures. + if (j != 0) + llinfos << out.str() << llendl; + } + llinfos << "\t Time points for each upload (start / finish)" << llendl; + for (U32 i = 0; i < LLVOAvatarDefines::BAKED_NUM_INDICES; ++i) + { + llinfos << "\t\t (" << i << ") \t" << (S32)mBakedTextureTimes[i][0] << " / " << (S32)mBakedTextureTimes[i][1] << llendl; + } } } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 460291a929..03856b3a3b 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -124,6 +124,11 @@ public: //-------------------------------------------------------------------- public: /*virtual*/ BOOL getIsCloud(); + void bakedTextureUpload(LLVOAvatarDefines::EBakedTextureIndex index, BOOL finished); + static void onTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); + void wearablesLoaded() { mTimeWearablesLoaded = mSelfLoadTimer.getElapsedTimeF32(); } + void avatarVisible() { mTimeAvatarVisible = mSelfLoadTimer.getElapsedTimeF32(); } + private: //-------------------------------------------------------------------- @@ -132,6 +137,14 @@ private: U64 mLastRegionHandle; LLFrameTimer mRegionCrossingTimer; S32 mRegionCrossingCount; + LLFrameTimer mSelfLoadTimer; + F32 mTimeWearablesLoaded; + F32 mTimeAvatarVisible; + F32 mTextureLoadTimes[LLVOAvatarDefines::TEX_NUM_INDICES][MAX_DISCARD_LEVEL+1]; // stores load time for each texture, + // at each discard level + F32 mBakedTextureTimes[LLVOAvatarDefines::BAKED_NUM_INDICES][2]; // stores time to start upload and finish upload of each baked texture + + void timingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); /** State ** ** @@ -332,6 +345,16 @@ public: ** ** *******************************************************************************/ +struct LLAvatarTexData +{ + LLAvatarTexData(const LLUUID& id, LLVOAvatarDefines::ETextureIndex index) : + mAvatarID(id), + mIndex(index) + {} + LLUUID mAvatarID; + LLVOAvatarDefines::ETextureIndex mIndex; +}; + }; extern LLVOAvatarSelf *gAgentAvatarp; diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index 3ecd1296bd..28613c8bcf 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -442,6 +442,9 @@ BOOL LLWearable::importFile( LLFILE* file ) delete mSavedTEMap[te]; } + image->setLoadedCallback(LLVOAvatarSelf::onTimingLocalTexLoaded,0,TRUE,FALSE, new LLVOAvatarSelf::LLAvatarTexData(id, (LLVOAvatarDefines::ETextureIndex)te)); + + LLUUID textureid(text_buffer); mTEMap[te] = new LLLocalTextureObject(image, textureid); mSavedTEMap[te] = new LLLocalTextureObject(image, textureid); 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 e30e958543..119dd63a17 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml @@ -1,16 +1,39 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" - height="660" + height="990" layout="topleft" name="avatar_texture_debug" help_topic="avatar_texture_debug" title="AVATAR TEXTURES" - width="1253"> + width="1240" + can_resize="true"> <floater.string name="InvalidAvatar"> INVALID AVATAR </floater.string> + + <scroll_container + color="DkGray2" + opaque="true" + follows="all" + height="970" + layout="topleft" + left="5" + top_pad="15" + name="profile_scroll" + reserve_scroll_corner="false" + width="1235"> + <panel + name="scroll_content_panel" + follows="left|top" + min_height="300" + layout="topleft" + top="0" + background_visible="false" + height="950" + left="0" + width="1230"> <text type="string" length="1" @@ -18,7 +41,7 @@ layout="topleft" left="30" name="label" - top="40" + top="20" width="80"> Baked Textures </text> @@ -43,27 +66,17 @@ top_delta="0" width="150" /> - <scroll_container - color="DkGray2" - opaque="true" - follows="all" - height="590" - layout="topleft" - left="5" - top_pad="5" - name="profile_scroll" - reserve_scroll_corner="false" - width="1240"> <panel name="scroll_content_panel" follows="left|top" min_height="300" layout="topleft" - top="0" + top="43" background_visible="false" - height="950" + height="930" left="0" - width="1250"> + width="1230"> + <texture_picker height="143" label="Hair" @@ -302,5 +315,6 @@ top_delta="0" width="128" /> </panel> +</panel> </scroll_container> -</floater> +</floater>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml index 5c30b9ee94..dc51ae8b92 100644 --- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml @@ -68,8 +68,8 @@ function="Self.EnableStandUp" /> </menu_item_call> <menu_item_call - label="My Appearance" - name="Appearance..."> + label="Change Outfit" + name="Change Outfit"> <menu_item_call.on_click function="CustomizeAvatar" /> <menu_item_call.on_enable diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml index a21c1ac44b..0efe598243 100644 --- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml @@ -183,9 +183,9 @@ </menu_item_call> </context_menu> <menu_item_call - label="My Appearance" + label="Change Outfit" layout="topleft" - name="Appearance..."> + name="Chenge Outfit"> <menu_item_call.on_click function="CustomizeAvatar" /> <menu_item_call.on_enable diff --git a/indra/newview/skins/default/xui/en/menu_bottomtray.xml b/indra/newview/skins/default/xui/en/menu_bottomtray.xml index 7ef91a1d85..5beafef4e4 100644 --- a/indra/newview/skins/default/xui/en/menu_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/menu_bottomtray.xml @@ -52,6 +52,50 @@ function="CheckControl" parameter="ShowSnapshotButton" /> </menu_item_check> + <menu_item_check + label="Build button" + layout="topleft" + name="ShowBuildButton"> + <menu_item_check.on_click + function="ToggleControl" + parameter="ShowBuildButton" /> + <menu_item_check.on_check + function="CheckControl" + parameter="ShowBuildButton" /> + </menu_item_check> + <menu_item_check + label="Search button" + layout="topleft" + name="ShowSearchButton"> + <menu_item_check.on_click + function="ToggleControl" + parameter="ShowSearchButton" /> + <menu_item_check.on_check + function="CheckControl" + parameter="ShowSearchButton" /> + </menu_item_check> + <menu_item_check + label="Map button" + layout="topleft" + name="ShowWorldMapButton"> + <menu_item_check.on_click + function="ToggleControl" + parameter="ShowWorldMapButton" /> + <menu_item_check.on_check + function="CheckControl" + parameter="ShowWorldMapButton" /> + </menu_item_check> + <menu_item_check + label="Mini-Map button" + layout="topleft" + name="ShowMiniMapButton"> + <menu_item_check.on_click + function="ToggleControl" + parameter="ShowMiniMapButton" /> + <menu_item_check.on_check + function="CheckControl" + parameter="ShowMiniMapButton" /> + </menu_item_check> <menu_item_separator name="Separator" /> <menu_item_call diff --git a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml index 03bd93e271..ea18e02ca1 100644 --- a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml @@ -16,8 +16,8 @@ function="Self.EnableStandUp" /> </menu_item_call> <menu_item_call - label="My Appearance" - name="my_appearance"> + label="Change Outfit" + name="change_outfit"> <menu_item_call.on_click function="CustomizeAvatar" /> <menu_item_call.on_enable diff --git a/indra/newview/skins/default/xui/en/menu_participant_list.xml b/indra/newview/skins/default/xui/en/menu_participant_list.xml index f126431263..4ed5807808 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_list.xml @@ -127,7 +127,8 @@ parameter="can_mute_text" /> </menu_item_check> <menu_item_separator - layout="topleft" /> + layout="topleft" + name="Moderator Options Separator"/> <context_menu label="Moderator Options >" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index c9ebeb60fb..16c2581d63 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -38,8 +38,8 @@ parameter="agent" /> </menu_item_call> <menu_item_call - label="My Appearance" - name="Appearance"> + label="Change Outfit" + name="ChangeOutfit"> <menu_item_call.on_click function="CustomizeAvatar" /> <menu_item_call.on_enable diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 4f46e34520..6b486a91c5 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3451,7 +3451,7 @@ You are not allowed in that region due to your maturity Rating. type="alertmodal"> You are not allowed in that Region due to your maturity Rating preference. -You can click 'Change Preference' to raise your maturity Rating preference now and allow you to enter. You will be able to search and access [REGIONMATURITY] content from now on. If you later want to change this setting back, go to Me > Preferences > General. +Click 'Change Preference' to raise your maturity Rating preference for immediate entry. Doing so will allow you to search for and access [REGIONMATURITY] content. If you wish to change this setting later, you may do so from Me > Preferences > General. <form name="form"> <button index="0" @@ -3470,7 +3470,7 @@ You can click 'Change Preference' to raise your maturity Rating prefer icon="notifytip.tga" name="PreferredMaturityChanged" type="notifytip"> -Your maturity rating preference is now [RATING]. +Your maturity Rating preference is now [RATING]. </notification> <notification @@ -6127,6 +6127,34 @@ Avatar '[NAME]' rezzed in [TIME] seconds. </notification> <notification + icon="notifytip.tga" + name="AvatarRezCloudNotification" + type="notifytip"> +Avatar '[NAME]' became cloud. + </notification> + + <notification + icon="notifytip.tga" + name="AvatarRezArrivedNotification" + type="notifytip"> +Avatar '[NAME]' appeared. + </notification> + + <notification + icon="notifytip.tga" + name="AvatarRezLeftCloudNotification" + type="notifytip"> +Avatar '[NAME]' left after [TIME] seconds as cloud. + </notification> + + <notification + icon="notifytip.tga" + name="AvatarRezLeftNotification" + type="notifytip"> +Avatar '[NAME]' left as fully loaded. + </notification> + + <notification icon="alertmodal.tga" name="ConfirmLeaveCall" type="alert"> @@ -6139,6 +6167,23 @@ Are you sure you want to leave this call? <unique/> </notification> + <notification + icon="alertmodal.tga" + name="ConfirmMuteAll" + type="alert"> +You have selected to mute all participants in a group call. +This will also cause all residents that later join the call to be +muted, even after you have left the call. + +Mute everyone? + <usetemplate + ignoretext="Confirm before I mute all participants in a group call" + name="okcancelignore" + notext="Ok" + yestext="Cancel"/> + <unique/> + </notification> + <global name="UnsupportedCPU"> - Your CPU speed does not meet the minimum requirements. </global> diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 7b11538ccc..620aabeeb8 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -10,7 +10,7 @@ left="0" name="bottom_tray" top="28" - width="1000"> + width="1310"> <string name="SpeakBtnToolTip" value="Turns microphone on/off" /> @@ -28,7 +28,7 @@ name="toolbar_stack" orientation="horizontal" top="0" - width="1000"> + width="1310"> <icon auto_resize="false" follows="left|right" @@ -211,6 +211,134 @@ </button> </layout_panel> <layout_panel + auto_resize="false" + follows="left|right" + height="28" + layout="topleft" + min_height="28" + min_width="52" + mouse_opaque="false" + name="build_btn_panel" + user_resize="false" + width="83"> +<!--*FIX: Build Floater is not opened with default registration. Will be fixed soon. +Disabled for now. +--> + <button +enabled="false" + follows="left|right" + height="23" + image_pressed="PushButton_Press" + image_pressed_selected="PushButton_Selected_Press" + image_selected="PushButton_Selected_Press" + is_toggle="true" + label="Build" + layout="topleft" + left="0" + name="build_btn" + tool_tip="Shows/hides Build Tools" + top="5" + use_ellipses="true" + width="80"> + <init_callback + function="Button.SetFloaterToggle" + parameter="build" /> + </button> + </layout_panel> + <layout_panel + auto_resize="false" + follows="left|right" + height="28" + layout="topleft" + min_height="28" + min_width="52" + mouse_opaque="false" + name="search_btn_panel" + user_resize="false" + width="83"> + <button + follows="left|right" + height="23" + image_pressed="PushButton_Press" + image_pressed_selected="PushButton_Selected_Press" + image_selected="PushButton_Selected_Press" + is_toggle="true" + label="Search" + layout="topleft" + left="0" + name="search_btn" + tool_tip="Shows/hides Search" + top="5" + use_ellipses="true" + width="80"> + <init_callback + function="Button.SetFloaterToggle" + parameter="search" /> + </button> + </layout_panel> + <layout_panel + auto_resize="false" + follows="left|right" + height="28" + layout="topleft" + min_height="28" + min_width="52" + mouse_opaque="false" + name="world_map_btn_panel" + user_resize="false" + width="83"> + <button + follows="left|right" + height="23" + image_pressed="PushButton_Press" + image_pressed_selected="PushButton_Selected_Press" + image_selected="PushButton_Selected_Press" + is_toggle="true" + label="Map" + layout="topleft" + left="0" + name="world_map_btn" + tool_tip="Shows/hides World Map" + top="5" + use_ellipses="true" + width="80"> + <init_callback + function="Button.SetFloaterToggle" + parameter="world_map" /> + </button> + </layout_panel> + <layout_panel + auto_resize="false" + follows="left|right" + height="28" + layout="topleft" + min_height="28" + min_width="52" + mouse_opaque="false" + name="mini_map_btn_panel" + user_resize="false" + width="83"> + <button + follows="left|right" + height="23" + image_pressed="PushButton_Press" + image_pressed_selected="PushButton_Selected_Press" + image_selected="PushButton_Selected_Press" + is_toggle="true" + label="Mini-Map" + layout="topleft" + left="0" + name="mini_map_btn" + tool_tip="Shows/hides Mini-Map" + top="5" + use_ellipses="true" + width="80"> + <init_callback + function="Button.SetFloaterToggle" + parameter="mini_map" /> + </button> + </layout_panel> + <layout_panel follows="left|right" height="30" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index 7961664516..9072418329 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -260,7 +260,7 @@ top_pad="5" left="0"> <layout_panel - auto_resize="true" + auto_resize="false" layout="topleft" follows="left|top|right" height="30" @@ -292,7 +292,7 @@ width="311" user_resize="true"> <inventory_panel - allow_multi_select="false" + allow_multi_select="true" border="false" follows="left|top|right|bottom" height="130" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 6d80b17ac6..bf28e78cf6 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -1894,6 +1894,7 @@ Clears (deletes) the media and all params from the given face. <string name="Wave" value=" Wave " /> <string name="HelloAvatar" value=" Hello, avatar! " /> <string name="ViewAllGestures" value=" View All >>" /> + <string name="GetMoreGestures" value=" Get More >>" /> <!-- inventory filter --> <!-- use value="" because they have preceding spaces --> @@ -3136,6 +3137,36 @@ Abuse Report</string> <string name="New Script">New Script</string> <string name="New Folder">New Folder</string> <string name="Contents">Contents</string> + <string name="Gesture">Gesture</string> + <string name="Male Gestures">Male Gestures</string> + <string name="Female Gestures">Female Gestures</string> + <string name="Other Gestures">Other Gestures</string> + <string name="Speech Gestures">Speech Gestures</string> + + <!-- gestures --> + <string name="Male - Excuse me">Male - Excuse me</string> + <string name="Male - Get lost">Male - Get lost</string> + <string name="Male - Blow kiss">Male - Blow kiss</string> + <string name="Male - Boo">Male - Boo</string> + <string name="Male - Bored">Male - Bored</string> + <string name="Male - Hey">Male - Hey</string> + <string name="Male - Laugh">Male - Laugh</string> + <string name="Male - Repulsed">Male - Repulsed</string> + <string name="Male - Shrug">Male - Shrug</string> + <string name="Male - Stick tougue out">Male - Stick tougue out</string> + <string name="Male - Wow">Male - Wow</string> + + <string name="FeMale - Excuse me">FeMale - Excuse me</string> + <string name="FeMale - Get lost">FeMale - Get lost</string> + <string name="FeMale - Blow kiss">FeMale - Blow kiss</string> + <string name="FeMale - Boo">FeMale - Boo</string> + <string name="Female - Bored">Female - Bored</string> + <string name="Female - Hey">Female - Hey</string> + <string name="Female - Laugh">Female - Laugh</string> + <string name="Female - Repulsed">Female - Repulsed</string> + <string name="Female - Shrug">Female - Shrug</string> + <string name="Female - Stick tougue out">Female - Stick tougue out</string> + <string name="Female - Wow">Female - Wow</string> <!-- birth date format shared by avatar inspector and profile panels --> <string name="AvatarBirthDateFormat">[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt]</string> 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 6190ea7872..216c4dea95 100644 --- a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml +++ b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml @@ -11,6 +11,7 @@ read_only="true" use_ellipses="true" word_wrap="true" + show_context_menu="true" tab_stop="true" v_pad="3" h_pad="4" > diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index 560465f808..261c49931e 100644 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -1630,25 +1630,25 @@ が渡しました </string> <string name="InvOfferYouDecline"> - You decline + 拒否: </string> <string name="InvOfferFrom"> - from + 送信元: </string> <string name="GroupMoneyTotal"> 合計 </string> <string name="GroupMoneyBought"> - は購入しました + 購入: </string> <string name="GroupMoneyPaidYou"> - があなたに支払いました + あなたに支払い: </string> <string name="GroupMoneyPaidInto"> paid into </string> <string name="GroupMoneyBoughtPassTo"> - bought pass to + 入場許可を購入: </string> <string name="GroupMoneyPaidFeeForEvent"> がイベント用の費用を支払いました |