From 7e90fd6e7f770213af9d586206479c8cf8ee5bbd Mon Sep 17 00:00:00 2001 From: Rye Mutt <rye@alchemyviewer.org> Date: Sun, 8 Oct 2023 02:13:33 -0400 Subject: [PATCH] Add derendering feature based on code from Catznip --- indra/llui/llscrolllistcell.cpp | 18 + indra/llui/llscrolllistcell.h | 24 + indra/llui/llscrolllistcolumn.cpp | 8 +- indra/llui/llscrolllistcolumn.h | 9 + indra/llui/llscrolllistctrl.cpp | 94 ++- indra/llui/llscrolllistctrl.h | 21 + indra/llui/llscrolllistitem.h | 8 + indra/newview/CMakeLists.txt | 4 + indra/newview/llagenthandler.cpp | 6 +- indra/newview/llchathistory.cpp | 6 +- indra/newview/llderenderlist.cpp | 431 ++++++++++ indra/newview/llderenderlist.h | 191 +++++ indra/newview/llfloaterblocked.cpp | 791 ++++++++++++++++++ indra/newview/llfloaterblocked.h | 245 ++++++ indra/newview/llfloaterbump.cpp | 6 +- indra/newview/llfloaterperformance.cpp | 2 +- indra/newview/llfloaterpreference.cpp | 9 +- indra/newview/llfloatersidepanelcontainer.cpp | 12 + indra/newview/llinspectremoteobject.cpp | 6 +- indra/newview/llnamelistctrl.cpp | 10 + indra/newview/llnamelistctrl.h | 6 +- indra/newview/llpanelblockedlist.cpp | 4 + indra/newview/llpanelblockedlist.h | 2 + indra/newview/llpanelpeople.cpp | 26 +- indra/newview/llpanelprofile.cpp | 2 +- indra/newview/llselectmgr.cpp | 9 +- indra/newview/llselectmgr.h | 4 +- indra/newview/llviewerfloaterreg.cpp | 6 + indra/newview/llviewermenu.cpp | 58 +- indra/newview/llviewermessage.cpp | 9 +- indra/newview/llviewerobjectlist.cpp | 33 + indra/newview/llviewerregion.cpp | 11 +- indra/newview/llvocache.cpp | 2 +- indra/newview/llvocache.h | 9 +- .../skins/default/xui/en/floater_blocked.xml | 60 ++ .../default/xui/en/menu_attachment_other.xml | 4 +- .../default/xui/en/menu_avatar_other.xml | 4 +- .../skins/default/xui/en/menu_object.xml | 20 + .../skins/default/xui/en/menu_viewer.xml | 8 +- .../xui/en/panel_block_avatar_rendering.xml | 106 +++ .../default/xui/en/panel_block_derender.xml | 65 ++ .../skins/default/xui/en/panel_block_list.xml | 124 +++ .../skins/default/xui/en/panel_people.xml | 4 +- 43 files changed, 2424 insertions(+), 53 deletions(-) create mode 100644 indra/newview/llderenderlist.cpp create mode 100644 indra/newview/llderenderlist.h create mode 100644 indra/newview/llfloaterblocked.cpp create mode 100644 indra/newview/llfloaterblocked.h create mode 100644 indra/newview/skins/default/xui/en/floater_blocked.xml create mode 100644 indra/newview/skins/default/xui/en/panel_block_avatar_rendering.xml create mode 100644 indra/newview/skins/default/xui/en/panel_block_derender.xml create mode 100644 indra/newview/skins/default/xui/en/panel_block_list.xml diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 2d3f87881fc..264d9eaf0df 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -78,6 +78,9 @@ LLScrollListCell* LLScrollListCell::create(const LLScrollListCell::Params& cell_ LLScrollListCell::LLScrollListCell(const LLScrollListCell::Params& p) : mWidth(p.width), +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + mColumnName(p.column), +// [/SL:KB] mToolTip(p.tool_tip) {} @@ -449,6 +452,14 @@ LLScrollListCheck::LLScrollListCheck(const LLScrollListCell::Params& p) { LLCheckBoxCtrl::Params checkbox_p; checkbox_p.name("checkbox"); +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + if (p.commit_callback.isProvided()) + { + if (!mCommitSignal) + mCommitSignal = new commit_signal_t(); + mCommitSignal->connect(p.commit_callback()); + } +// [/SL:KB] checkbox_p.rect = LLRect(0, p.width, p.width, 0); checkbox_p.enabled(p.enabled); checkbox_p.initial_value(p.value()); @@ -473,6 +484,9 @@ LLScrollListCheck::LLScrollListCheck(const LLScrollListCell::Params& p) LLScrollListCheck::~LLScrollListCheck() { +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + delete mCommitSignal; +// [/SL:KB] delete mCheckBox; mCheckBox = NULL; } @@ -508,6 +522,10 @@ void LLScrollListCheck::setValue(const LLSD& value) void LLScrollListCheck::onCommit() { mCheckBox->onCommit(); +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + if (mCommitSignal) + (*mCommitSignal)(this); +// [/SL:KB] } /*virtual*/ diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h index 0a7aaaf6ee5..9964cc9454e 100644 --- a/indra/llui/llscrolllistcell.h +++ b/indra/llui/llscrolllistcell.h @@ -36,6 +36,9 @@ #include "llgltexture.h" #include "lllineeditor.h" +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 +#include "lluictrl.h" +// [/SL:KB] class LLCheckBoxCtrl; class LLSD; @@ -52,6 +55,11 @@ class LLUIImage; class LLScrollListCell { public: +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + typedef boost::function<void(LLScrollListCell* cell)> commit_callback_t; + typedef boost::signals2::signal<void(LLScrollListCell* cell)> commit_signal_t; +// [/SL:KB] + struct Params : public LLInitParam::Block<Params> { Optional<std::string> type, @@ -61,6 +69,10 @@ class LLScrollListCell Optional<bool> enabled, visible; +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + Optional<commit_callback_t> commit_callback; +// [/SL:KB] + Optional<void*> userdata; Optional<LLSD> value; // state of checkbox, icon id/name, date Optional<LLSD> alt_value; @@ -79,6 +91,9 @@ class LLScrollListCell width("width"), enabled("enabled", true), visible("visible", true), +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + commit_callback("commit_callback"), +// [/SL:KB] value("value"), alt_value("alt_value", ""), label("label"), @@ -106,6 +121,9 @@ class LLScrollListCell virtual const LLSD getAltValue() const; virtual void setValue(const LLSD& value) { } virtual void setAltValue(const LLSD& value) { } +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + virtual const std::string &getColumnName() const { return mColumnName; } +// [/SL:KB] virtual const std::string &getToolTip() const { return mToolTip; } virtual void setToolTip(const std::string &str) { mToolTip = str; } virtual BOOL getVisible() const { return TRUE; } @@ -121,6 +139,9 @@ class LLScrollListCell private: S32 mWidth; +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + std::string mColumnName; +// [/SL:KB] std::string mToolTip; }; @@ -250,6 +271,9 @@ class LLScrollListCheck : public LLScrollListCell private: LLCheckBoxCtrl* mCheckBox; +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + commit_signal_t* mCommitSignal = nullptr; +// [/SL:KB] }; class LLScrollListDate : public LLScrollListText diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp index bddf1b074b4..dc89a761308 100644 --- a/indra/llui/llscrolllistcolumn.cpp +++ b/indra/llui/llscrolllistcolumn.cpp @@ -109,7 +109,10 @@ BOOL LLScrollColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask) void LLScrollColumnHeader::onClick(const LLSD& data) { - if (mColumn) +// if (mColumn) +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + if ( (mColumn) && (mColumn->mCanSort) ) +// [/SL:KB] { LLScrollListCtrl::onClickColumn(mColumn); } @@ -313,6 +316,9 @@ LLScrollListColumn::LLScrollListColumn(const Params& p, LLScrollListCtrl* parent mDynamicWidth(p.width.dynamic_width), mRelWidth(p.width.relative_width), mFontAlignment(p.halign), +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + mCanSort(p.can_sort), +// [/SL:KB] mSortingColumn(p.sort_column) { if (p.sort_ascending.isProvided()) diff --git a/indra/llui/llscrolllistcolumn.h b/indra/llui/llscrolllistcolumn.h index cc29db0b702..098f3e5ffbd 100644 --- a/indra/llui/llscrolllistcolumn.h +++ b/indra/llui/llscrolllistcolumn.h @@ -91,6 +91,9 @@ class LLScrollListColumn { Optional<std::string> name, tool_tip; +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + Optional<bool> can_sort; +// [/SL:KB] Optional<std::string> sort_column; Optional<ESortDirection, SortNames> sort_direction; Optional<bool> sort_ascending; @@ -129,6 +132,9 @@ class LLScrollListColumn Params() : name("name"), tool_tip("tool_tip"), +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + can_sort("can_sort", true), +// [/SL:KB] sort_column("sort_column"), sort_direction("sort_direction"), sort_ascending("sort_ascending", true), @@ -154,6 +160,9 @@ class LLScrollListColumn // If it ever gets any smarter than that, these should all become private // with protected or public accessor methods added as needed. -MG std::string mName; +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + bool mCanSort; +// [/SL:KB] std::string mSortingColumn; ESortDirection mSortDirection; LLUIString mLabel; diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index bd84e486c96..a76a000b767 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -151,6 +151,9 @@ LLScrollListCtrl::Params::Params() mouse_wheel_opaque("mouse_wheel_opaque", false), commit_on_keyboard_movement("commit_on_keyboard_movement", true), commit_on_selection_change("commit_on_selection_change", false), +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + select_on_focus("select_on_focus", true), +// [/SL:KB] heading_height("heading_height"), page_lines("page_lines", 0), background_visible("background_visible"), @@ -182,6 +185,12 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) mAllowKeyboardMovement(true), mCommitOnKeyboardMovement(p.commit_on_keyboard_movement), mCommitOnSelectionChange(p.commit_on_selection_change), +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-3.3 + mCommitOnDelete(false), +// [/SL:KB] +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + mSelectOnFocus(p.select_on_focus), +// [/SL:KB] mSelectionChanged(false), mSelectionType(p.selection_type), mNeedsScroll(false), @@ -427,6 +436,13 @@ void LLScrollListCtrl::clearRows() mLastSelected = NULL; updateLayout(); mDirty = false; + +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-3.3 + if (mCommitOnDelete) + { + onCommit(); + } +// [/SL:KB] } @@ -1032,7 +1048,38 @@ void LLScrollListCtrl::deleteSingleItem(S32 target_index) delete itemp; mItemList.erase(mItemList.begin() + target_index); dirtyColumns(); + +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-3.3 + if (mCommitOnDelete) + { + onCommit(); + } +// [/SL:KB] +} + +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-3.5 +void LLScrollListCtrl::deleteSingleItem(LLScrollListItem* itemp) +{ + item_list::iterator itItem = std::find(mItemList.begin(), mItemList.end(), itemp); + if (mItemList.end() == itItem) + { + return; + } + + if (mLastSelected == itemp) + { + mLastSelected = nullptr; + } + delete itemp; + mItemList.erase(itItem); + dirtyColumns(); + + if (mCommitOnDelete) + { + onCommit(); + } } +// [/SL:KB] //FIXME: refactor item deletion void LLScrollListCtrl::deleteItems(const LLSD& sd) @@ -1057,6 +1104,13 @@ void LLScrollListCtrl::deleteItems(const LLSD& sd) } dirtyColumns(); + +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-3.3 + if (mCommitOnDelete) + { + onCommit(); + } +// [/SL:KB] } void LLScrollListCtrl::deleteSelectedItems() @@ -1077,6 +1131,13 @@ void LLScrollListCtrl::deleteSelectedItems() } mLastSelected = NULL; dirtyColumns(); + +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-3.3 + if (mCommitOnDelete) + { + onCommit(); + } +// [/SL:KB] } void LLScrollListCtrl::clearHighlightedItems() @@ -3091,6 +3152,9 @@ void LLScrollListCtrl::addColumn(const LLScrollListColumn::Params& column_params params.tool_tip = column_params.tool_tip; params.tab_stop = false; params.visible = mDisplayColumnHeaders; +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + params.font_halign = column_params.halign; +// [/SL:KB] if(column_params.header.image.isProvided()) { @@ -3158,6 +3222,13 @@ const std::string& LLScrollListCtrl::getSortColumnName() return LLStringUtil::null; } +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-3.5 +S32 LLScrollListCtrl::getSortColumnIndex() const +{ + return (!mSortColumns.empty()) ? mSortColumns.back().first : -1; +} +// [/SL:KB] + BOOL LLScrollListCtrl::hasSortOrder() const { return !mSortColumns.empty(); @@ -3233,6 +3304,17 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition return addRow(item_params, pos); } +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 +LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, const LLScrollListItem::commit_signal_t::slot_type& cb, EAddPosition pos) +{ + LLScrollListItem::Params item_params; + LLParamSDParser parser; + parser.readSD(element, item_params); + item_params.commit_callback = cb; + return addRow(item_params, pos); +} +// [/SL:KB] + LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos) { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; @@ -3288,6 +3370,13 @@ LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLS cell_p.width = columnp->getWidth(); } +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + if (item_p.commit_callback.isProvided()) + { + cell_p.commit_callback = boost::bind(item_p.commit_callback(), item_p.value(), _1); + } +// [/SL:KB] + LLScrollListCell* cell = LLScrollListCell::create(cell_p); if (cell) @@ -3417,7 +3506,10 @@ BOOL LLScrollListCtrl::operateOnAll(EOperation op) void LLScrollListCtrl::setFocus(BOOL b) { // for tabbing into pristine scroll lists (Finder) - if (!getFirstSelected()) +// if (!getFirstSelected()) +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + if ( (mSelectOnFocus) && (!getFirstSelected()) ) +// [/SL:KB] { selectFirstItem(); //onCommit(); // SJB: selectFirstItem() will call onCommit() if appropriate diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index bef7bc72ef4..07b7cea4165 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -110,6 +110,9 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, Optional<bool> multi_select, commit_on_keyboard_movement, commit_on_selection_change, +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + select_on_focus, +// [/SL:KB] mouse_wheel_opaque; Optional<ESelectionType, SelectionTypeNames> selection_type; @@ -185,6 +188,9 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, // "columns" => [ "column" => column name, "value" => value, "type" => type, "font" => font, "font-style" => style ], "id" => uuid // Creates missing columns automatically. virtual LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + virtual LLScrollListItem* addElement(const LLSD& element, const LLScrollListItem::commit_signal_t::slot_type& cb, EAddPosition pos = ADD_BOTTOM); +// [/SL:KB] virtual LLScrollListItem* addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM); virtual LLScrollListItem* addRow(const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM); // Simple add element. Takes a single array of: @@ -229,6 +235,9 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, BOOL selectItemAt(S32 x, S32 y, MASK mask); void deleteSingleItem( S32 index ); +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-3.5 + void deleteSingleItem(LLScrollListItem* itemp); +// [/SL:KB] void deleteItems(const LLSD& sd); void deleteSelectedItems(); void deselectAllItems(BOOL no_commit_on_change = FALSE); // by default, go ahead and commit on selection change @@ -316,6 +325,9 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, S32 getRowPadding() const { return mColumnPadding; } void setCommitOnKeyboardMovement(BOOL b) { mCommitOnKeyboardMovement = b; } void setCommitOnSelectionChange(BOOL b) { mCommitOnSelectionChange = b; } +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-3.3 + void setCommitOnDelete(BOOL b) { mCommitOnDelete = b; } +// [/SL:KB] void setAllowKeyboardMovement(BOOL b) { mAllowKeyboardMovement = b; } void setMaxSelectable(U32 max_selected) { mMaxSelectable = max_selected; } @@ -410,6 +422,9 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, S32 getTotalStaticColumnWidth() { return mTotalStaticColumnWidth; } const std::string& getSortColumnName(); +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-3.5 + S32 getSortColumnIndex() const; +// [/SL:KB] BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; } BOOL hasSortOrder() const; void clearSortOrder(); @@ -495,6 +510,12 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, bool mAllowKeyboardMovement; bool mCommitOnKeyboardMovement; bool mCommitOnSelectionChange; +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-3.3 + bool mCommitOnDelete; +// [/SL:KB] +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + bool mSelectOnFocus = true; +// [/SL:KB] bool mSelectionChanged; ESelectionType mSelectionType; bool mNeedsScroll; diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h index a3398305b17..60f45963400 100644 --- a/indra/llui/llscrolllistitem.h +++ b/indra/llui/llscrolllistitem.h @@ -50,9 +50,17 @@ class LLScrollListItem { friend class LLScrollListCtrl; public: +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + typedef boost::function<void(const LLSD& value, LLScrollListCell* cell)> commit_callback_t; + typedef boost::signals2::signal<void(const LLSD& value, LLScrollListCell* cell)> commit_signal_t; +// [/SL:KB] + struct Params : public LLInitParam::Block<Params> { Optional<bool> enabled; +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + Optional<commit_callback_t> commit_callback; +// [/SL:KB] Optional<void*> userdata; Optional<LLSD> value; Optional<LLSD> alt_value; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0d4b8e1f30d..cef9ed018c5 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -177,6 +177,7 @@ set(viewer_SOURCE_FILES lldebugview.cpp lldeferredsounds.cpp lldelayedgestureerror.cpp + llderenderlist.cpp lldirpicker.cpp lldonotdisturbnotificationstorage.cpp lldndbutton.cpp @@ -229,6 +230,7 @@ set(viewer_SOURCE_FILES llfloaterbanduration.cpp llfloaterbeacons.cpp llfloaterbigpreview.cpp + llfloaterblocked.cpp llfloaterbuildoptions.cpp llfloaterbulkpermission.cpp llfloaterbump.cpp @@ -902,6 +904,7 @@ set(viewer_HEADER_FILES lldebugview.h lldeferredsounds.h lldelayedgestureerror.h + llderenderlist.h lldirpicker.h lldonotdisturbnotificationstorage.h lldndbutton.h @@ -954,6 +957,7 @@ set(viewer_HEADER_FILES llfloaterbanduration.h llfloaterbeacons.h llfloaterbigpreview.h + llfloaterblocked.h llfloaterbuildoptions.h llfloaterbulkpermission.h llfloaterbump.h diff --git a/indra/newview/llagenthandler.cpp b/indra/newview/llagenthandler.cpp index 736595b4882..f2b46e0e906 100644 --- a/indra/newview/llagenthandler.cpp +++ b/indra/newview/llagenthandler.cpp @@ -32,7 +32,8 @@ #include "llfloaterreporter.h" #include "llmutelist.h" #include "llnotificationsutil.h" -#include "llpanelblockedlist.h" +//#include "llpanelblockedlist.h" +#include "llfloaterblocked.h" class LLAgentHandler : public LLCommandHandler { @@ -148,7 +149,8 @@ class LLAgentHandler : public LLCommandHandler const std::string object_name = LLURI::unescape(params[2].asString()); LLMute mute(avatar_id, object_name, LLMute::OBJECT); LLMuteList::getInstance()->add(mute); - LLPanelBlockedList::showPanelAndSelect(mute.mID); + LLFloaterBlocked::showMuteAndSelect(mute.mID); + //LLPanelBlockedList::showPanelAndSelect(mute.mID); } return true; } diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 816984b296d..dbc5bcb178d 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -65,6 +65,7 @@ #include "lluiconstants.h" #include "llstring.h" #include "llurlaction.h" +#include "llfloaterblocked.h" // [SL:KB] - Patch: Chat-Alerts | Checked: 2012-07-10 (Catznip-3.3) #include "llaudioengine.h" #include "lltextparser.h" @@ -190,8 +191,9 @@ class LLChatHistoryHeader: public LLPanel { LLMuteList::getInstance()->add(LLMute(getAvatarId(), mFrom, LLMute::OBJECT)); - LLFloaterSidePanelContainer::showPanel("people", "panel_people", - LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId())); + LLFloaterBlocked::showMuteAndSelect(getAvatarId()); + //LLFloaterSidePanelContainer::showPanel("people", "panel_people", + // LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId())); } else if (level == "unblock") { diff --git a/indra/newview/llderenderlist.cpp b/indra/newview/llderenderlist.cpp new file mode 100644 index 00000000000..78f28c481d6 --- /dev/null +++ b/indra/newview/llderenderlist.cpp @@ -0,0 +1,431 @@ +/** + * + * Copyright (c) 2011-2014, Kitty Barnett + * + * The source code in this file is provided to you under the terms of the + * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt + * + * By copying, modifying or distributing this software, you acknowledge that + * you have read and understood your obligations described above, and agree to + * abide by those obligations. + * + */ +#include "llviewerprecompiledheaders.h" + +#include "llagent.h" +#include "llderenderlist.h" +#include "llsdserialize.h" +#include "llselectmgr.h" +#include "lltrans.h" +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llvocache.h" +#include "llvoavatarself.h" +#include "llworld.h" +#include "pipeline.h" + +// ============================================================================ +// LLDerenderEntry +// + +LLDerenderEntry::LLDerenderEntry(EEntryType eType, bool fPersists) + : m_eType(eType), m_nFlags(FLAG_NONE) +{ + if (fPersists) + m_nFlags |= FLAG_PERSIST; +} + +LLDerenderEntry::LLDerenderEntry(EEntryType eType, const LLSD& sdData) + : m_eType(TYPE_NONE) +{ + // Sanity check + if ( (sdData.has("entry_type")) && (eType != sdData["entry_type"].asInteger()) ) + { + LL_WARNS("Derender") << "Attempting to parse derender entry with reported type of " << sdData["entry_type"].asInteger() << " as type " << eType << LL_ENDL; + return; + } + m_eType = eType; + + // Pre-flags legacy support + m_nFlags = (sdData.has("entry_flags")) ? sdData["entry_flags"].asInteger() : FLAG_PERSIST; + + // Legacy support for object_id + m_idEntry = (sdData.has("entry_id")) ? sdData["entry_id"].asUUID() : sdData["object_id"].asUUID(); + + // Legacy support for object_name + m_strEntryName = (sdData.has("entry_name")) ? sdData["entry_name"].asString(): sdData["object_name"].asString(); + if (m_strEntryName.empty()) + m_strEntryName = LLTrans::getString("Unknown"); +} + +std::unique_ptr<LLDerenderEntry> LLDerenderEntry::fromLLSD(const LLSD& sdData) +{ + EEntryType eType = (sdData.has("entry_type")) ? (EEntryType)sdData["entry_type"].asInteger() : TYPE_OBJECT; + switch (eType) + { + case TYPE_OBJECT: + return std::make_unique<LLDerenderObject>(sdData); + case TYPE_AVATAR: + return std::make_unique<LLDerenderAvatar>(sdData); + default: + return nullptr; + } +} + +LLSD LLDerenderEntry::toLLSD() const +{ + LLSD sdData; + + sdData["entry_type"] = m_eType; + sdData["entry_flags"] = m_nFlags; + sdData["entry_name"] = m_strEntryName; + sdData["entry_id"] = m_idEntry; + + return sdData; +} + +// ============================================================================ +// LLDerenderObject +// + +LLDerenderObject::LLDerenderObject(const LLSelectNode* pNode, bool fPersist) + : LLDerenderEntry(TYPE_OBJECT, fPersist), idRegion(0), idRootLocal(0) +{ + // + // Fill in all object related information + // + const LLViewerObject* pObj = (pNode) ? pNode->getObject() : nullptr; + if (!pObj) + return; + + m_idEntry = pObj->getID(); + m_strEntryName = ((pNode->mValid) && (!pNode->mName.empty())) ? pNode->mName : LLTrans::getString("Unknown"); + + idRootLocal = pObj->getLocalID(); + for (LLViewerObject::const_child_list_t::const_iterator itChild = pObj->getChildren().begin(), endChild = pObj->getChildren().end(); itChild != endChild; ++itChild) + idsChildLocal.push_back((*itChild)->getLocalID()); + + // + // Fill in all region related information + // + if (const LLViewerRegion* pRegion = pObj->getRegion()) + { + idRegion = pRegion->getHandle(); + posRegion = pObj->getPositionRegion(); + strRegionName = pRegion->getName(); + } + if (strRegionName.empty()) + { + strRegionName = LLTrans::getString("Unknown"); + } +} + +LLDerenderObject::LLDerenderObject(const LLSD& sdData) + : LLDerenderEntry(TYPE_OBJECT, sdData), idRegion(0), idRootLocal(0) +{ + if (sdData.has("region_pos")) + posRegion.setValue(sdData["region_pos"]); + strRegionName = (sdData.has("region_name")) ? sdData["region_name"].asString() : LLTrans::getString("Unknown"); +} + +LLSD LLDerenderObject::toLLSD() const +{ + LLSD sdData = LLDerenderEntry::toLLSD(); + + sdData["region_name"] = strRegionName; + sdData["region_pos"] = posRegion.getValue(); + + return sdData; +} + +// ============================================================================ +// LLDerenderList +// + +LLDerenderList::change_signal_t LLDerenderList::s_ChangeSignal; +std::string LLDerenderList::s_PersistFilename = "derender_list.llsd"; + +LLDerenderList::LLDerenderList() +{ + load(); +} + +LLDerenderList::~LLDerenderList() +{ +} + +void LLDerenderList::load() +{ + llifstream fileDerender(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, s_PersistFilename)); + if (!fileDerender.is_open()) + { + LL_WARNS() << "Can't open derender list file \"" << s_PersistFilename << "\" for reading" << LL_ENDL; + return; + } + + m_Entries.clear(); + + LLSD inSD; + S32 ret = LLSDSerialize::fromNotation(inSD, fileDerender, LLSDSerialize::SIZE_UNLIMITED); + fileDerender.close(); + if (ret == LLSDParser::PARSE_FAILURE || !inSD.isArray()) + { + return; + } + + for (const LLSD& sdEntry : inSD.array()) + { + auto pEntry = LLDerenderEntry::fromLLSD(sdEntry); + if (pEntry->isValid()) + m_Entries.push_back(std::move(pEntry)); + } +} + +void LLDerenderList::save() const +{ + llofstream fileDerender(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, s_PersistFilename)); + if (!fileDerender.is_open()) + { + LL_WARNS() << "Can't open derender list file \"" << s_PersistFilename << "\" for writing" << LL_ENDL; + return; + } + + LLSD outSD; + for (const auto& pEntry : m_Entries) + { + if (pEntry->isPersistent()) + outSD.append(pEntry->toLLSD()); + } + + LLSDSerialize::toNotation(outSD, fileDerender); + + fileDerender.close(); +} + +// ============================================================================ +// Entry helper functions +// + +LLDerenderList::entry_list_t::iterator LLDerenderList::findEntry(LLDerenderEntry::EEntryType eType, const LLUUID& idEntry) +{ + return std::find_if(m_Entries.begin(), m_Entries.end(), [eType, &idEntry](const auto& e) { return (eType == e->getType()) && (idEntry == e->getID()); }); +} + +LLDerenderList::entry_list_t::iterator LLDerenderList::findObjectEntry(U64 idRegion, const LLUUID& idObject, U32 idRootLocal) +{ + // NOTE: 'idRootLocal' will be 0 for the root prim itself and is the only time we need to compare against 'idObject' + return std::find_if(m_Entries.begin(), m_Entries.end(), + [&idRegion, &idObject, &idRootLocal](const std::unique_ptr<LLDerenderEntry>& e) + { return (LLDerenderEntry::TYPE_OBJECT == e->getType()) && + ( ((idRootLocal) && (idRegion == ((LLDerenderObject*)e.get())->idRegion) && (idRootLocal == ((LLDerenderObject*)e.get())->idRootLocal)) || (idObject == e->getID()) ); }); +} + +void LLDerenderList::removeObject(LLDerenderEntry::EEntryType eType, const LLUUID& idObject) +{ + uuid_vec_t idsObject; + idsObject.push_back(idObject); + removeObjects(eType, idsObject); +} + +void LLDerenderList::removeObjects(LLDerenderEntry::EEntryType eType, const uuid_vec_t& idsObject) +{ + bool fSave = false; + std::map<LLViewerRegion*, std::list<U32>> idRegionObjectMap; // TYPE_OBJECT + + for (const auto& idObject : idsObject) + { + entry_list_t::iterator itEntry = findEntry(eType, idObject); + if (m_Entries.end() == itEntry) + continue; + + const auto& pEntry = *itEntry; + switch (eType) + { + case LLDerenderEntry::TYPE_OBJECT: + { + LLDerenderObject* pObjEntry = static_cast<LLDerenderObject*>(pEntry.get()); + if (0 == pObjEntry->idRegion) + continue; + + if (LLViewerRegion* pRegion = LLWorld::getInstance()->getRegionFromHandle(pObjEntry->idRegion)) + { + std::list<U32>& idsLocal = idRegionObjectMap[pRegion]; + if (pObjEntry->idRootLocal) + idsLocal.push_back(pObjEntry->idRootLocal); + idsLocal.splice(idsLocal.end(), pObjEntry->idsChildLocal); + } + } + break; + } + fSave |= pEntry->isPersistent(); + + m_Entries.erase(itEntry); + } + + // TYPE_OBJECT + for (const auto& data_pair : idRegionObjectMap) + { + LLViewerRegion* pRegion = data_pair.first; + for (U32 local_id : data_pair.second) + pRegion->addCacheMissFull(local_id); + pRegion->requestCacheMisses(); + } + + if (fSave) + save(); + s_ChangeSignal(); +} + +// ============================================================================ +// Object handling functions +// + +bool LLDerenderList::addSelection(bool fPersist, std::vector<LLUUID>* pIdList) +{ + if (pIdList) + { + pIdList->clear(); + } + + LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); + + LLObjectSelection::root_iterator itObj = hSel->root_begin(); + while (hSel->root_end() != itObj) + { + const LLSelectNode* pNode = *itObj++; + if (!canAdd(pNode->getObject())) + continue; + + auto uniqueEntry = std::make_unique<LLDerenderObject>(pNode, fPersist); + if (!uniqueEntry || (isDerendered(uniqueEntry->getID())) || (gAgentID == uniqueEntry->getID()) ) + continue; + + auto pEntry = uniqueEntry.get(); + m_Entries.push_back(std::move(uniqueEntry)); + + if (pIdList) + { + pIdList->push_back(pEntry->getID()); + } + + LLViewerObject* pObj = pNode->getObject(); + if (pObj) + { + // Display green bubble on kill [see process_kill_object()] + if (gShowObjectUpdates) + gPipeline.addDebugBlip(pObj->getPositionAgent(), LLColor4(0.f, 1.f, 0.f, 1.f)); + // Keep the order of these the same as process_kill_object() + LLViewerRegion* pObjRegion = pObj->getRegion(); U32 idObjLocal = pObj->getLocalID(); + gObjectList.killObject(pObj); + if ( (LLViewerRegion::sVOCacheCullingEnabled) && (pObjRegion) ) + pObjRegion->killCacheEntry(idObjLocal); + LLSelectMgr::getInstance()->removeObjectFromSelections(pEntry->getID()); + } + } + + if (fPersist) + save(); + s_ChangeSignal(); + return (!pIdList) || (!pIdList->empty()); +} + +bool LLDerenderList::canAdd(const LLViewerObject* pObj) +{ + // Allow derendering if: + return + // - the object isn't a child prim + (pObj) && (pObj->getRootEdit() == pObj) && + // - the object isn't currently sat on by the user + ( (isAgentAvatarValid()) && (!pObj->isChild(gAgentAvatarp)) ) && + // - the object isn't an attachment + (!pObj->isAttachment()); +} + +bool LLDerenderList::canAddSelection() +{ + struct CanDerender : public LLSelectedObjectFunctor + { + /*virtual*/ bool apply(LLViewerObject* pObj) { return LLDerenderList::canAdd(pObj); } + } f; + LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); + return (hSel.notNull()) && (0 != hSel->getRootObjectCount()) && (hSel->applyToRootObjects(&f, false)); +} + +LLDerenderObject* LLDerenderList::getObjectEntry(const LLUUID& idObject) /*const*/ +{ + LLDerenderList::entry_list_t::iterator itEntry = findEntry(LLDerenderEntry::TYPE_OBJECT, idObject); + return (m_Entries.end() != itEntry) ? (LLDerenderObject*)itEntry->get() : NULL; +} + +LLDerenderObject* LLDerenderList::getObjectEntry(U64 idRegion, const LLUUID& idObject, U32 idRootLocal) /*const*/ +{ + LLDerenderList::entry_list_t::const_iterator itEntry = findObjectEntry(idRegion, idObject, idRootLocal); + return (m_Entries.end() != itEntry) ? (LLDerenderObject*)itEntry->get() : NULL; +} + +bool LLDerenderList::processObjectUpdate(U64 idRegion, const LLUUID& idObject, const LLVOCacheEntry* pCacheEntry) +{ + // Used by OUT_FULL_CACHED + if (!pCacheEntry->isChild()) + { + // We know it's a root prim so we can skip looking up its parent + LLDerenderObject* pObjEntry = getObjectEntry(idObject); + if (!pObjEntry) + { + return false; // Not a derendered object + } + + // Update root prim information + pObjEntry->idRegion = idRegion; + pObjEntry->idRootLocal = pCacheEntry->getLocalID(); + + // We can use the object cache entry to give us all child prims IDs + pObjEntry->idsChildLocal.clear(); + for (LLVOCacheEntry::vocache_entry_set_t::const_iterator itChild = pCacheEntry->getChildrenBegin(), endChild = pCacheEntry->getChildrenEnd(); itChild != endChild; ++itChild) + pObjEntry->idsChildLocal.push_back((*itChild)->getLocalID()); + + return true; + } + + // Child prim so perform normal processing + return processObjectUpdate(idRegion, idObject, pCacheEntry->getLocalID(), pCacheEntry->getDP()->getBuffer()); +} + +bool LLDerenderList::processObjectUpdate(U64 idRegion, const LLUUID& idObject, U32 idObjectLocal, U32 idRootLocal) +{ + // Used by OUT_FULL + LLDerenderObject* pObjEntry = (0 == idRootLocal) ? getObjectEntry(idObject) : getObjectEntry(idRegion, idObject, idRootLocal); + if (pObjEntry) + { + if (0 != idRootLocal) + { + // We're updating a child prim + if (pObjEntry->idsChildLocal.end() == std::find(pObjEntry->idsChildLocal.begin(), pObjEntry->idsChildLocal.end(), idObjectLocal)) + pObjEntry->idsChildLocal.push_back(idObjectLocal); + } + else + { + // We're updating the root prim + pObjEntry->idRegion = idRegion; + pObjEntry->idRootLocal = idObjectLocal; + } + return true; + } + return false; +} + +bool LLDerenderList::processObjectUpdate(U64 idRegion, const LLUUID& idObject, U32 idObjectLocal, const U8* pBuffer) +{ + // Used by OUT_FULL_COMPRESSED + U32 idRootLocal = 0, nMask = 0; + htolememcpy(&nMask, pBuffer + 64, MVT_U32, 4); // "SpecialCode" + if (nMask & 0x20) + htolememcpy(&idRootLocal, pBuffer + 84, MVT_U32, 4); // "ParentID" + return processObjectUpdate(idRegion, idObject, idObjectLocal, idRootLocal); +} + +// ============================================================================ diff --git a/indra/newview/llderenderlist.h b/indra/newview/llderenderlist.h new file mode 100644 index 00000000000..3a307d3c2b4 --- /dev/null +++ b/indra/newview/llderenderlist.h @@ -0,0 +1,191 @@ +/** + * + * Copyright (c) 2011-2014, Kitty Barnett + * + * The source code in this file is provided to you under the terms of the + * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt + * + * By copying, modifying or distributing this software, you acknowledge that + * you have read and understood your obligations described above, and agree to + * abide by those obligations. + * + */ +#ifndef LL_DERENDERLIST_H +#define LL_DERENDERLIST_H + +#include "llsingleton.h" +#include "lluuid.h" + +// ============================================================================ +// Forward declarations +// + +class LLSelectNode; +class LLVOCacheEntry; +class LLViewerObject; + +// ============================================================================ +// LLDerenderEntry +// + +class LLDerenderEntry +{ + /* + * Type declarations + */ +public: + enum EEntryType + { + TYPE_OBJECT = 0, + TYPE_AVATAR, + TYPE_ALL, + TYPE_NONE + }; + + enum + { + FLAG_NONE = 0x00, + FLAG_PERSIST = 0x01 + }; + + /* + * Constructors + */ +protected: + LLDerenderEntry(EEntryType eType, bool fPersists); + LLDerenderEntry(EEntryType eType, const LLSD& sdData); +public: + virtual ~LLDerenderEntry() {} + + /* + * Member functions + */ +public: + std::string getName() const { return m_strEntryName; } + const LLUUID& getID() const { return m_idEntry; } + EEntryType getType() const { return m_eType; } + bool isPersistent() const { return m_nFlags & FLAG_PERSIST; } + bool isValid() const { return (m_eType != TYPE_NONE) && (m_idEntry.notNull()); } + + static std::unique_ptr<LLDerenderEntry> fromLLSD(const LLSD& sdData); + virtual LLSD toLLSD() const; + + /* + * Member variables + */ +protected: + EEntryType m_eType; + S32 m_nFlags; + LLUUID m_idEntry; + std::string m_strEntryName; +}; + +// ============================================================================ +// LLDerenderObject +// + +class LLDerenderObject : public LLDerenderEntry +{ + /* + * Constructors + */ +public: + LLDerenderObject(const LLSelectNode* pNode, bool fPersist); + LLDerenderObject(const LLSD& sdData); + + /* + * Base class overrides + */ +public: + /*virtual*/ LLSD toLLSD() const; + + /* + * Member variables + */ +public: + std::string strRegionName; // Region name + LLVector3 posRegion; // Position of the object on the region + U64 idRegion; // Region handle + U32 idRootLocal; // Local object ID of the root (region-specific) + std::list<U32> idsChildLocal; // Local object ID of all child prims +}; + +// ============================================================================ +// LLDerenderAvatar +// + +class LLDerenderAvatar : public LLDerenderEntry +{ +public: + LLDerenderAvatar(bool fPersists) + : LLDerenderEntry(TYPE_AVATAR, fPersists) + { + } + LLDerenderAvatar(const LLSD& sdData) + : LLDerenderEntry(TYPE_AVATAR, sdData) + { + } +}; + +// ============================================================================ +// LLDerenderList +// + +class LLDerenderList : public LLSingleton<LLDerenderList> +{ + LLSINGLETON(LLDerenderList); +protected: + /*virtual*/ ~LLDerenderList(); + + void load(); + void save() const; + + /* + * Entry helper functions + */ +public: + using entry_list_t = std::list<std::unique_ptr<LLDerenderEntry>>; + + const entry_list_t& getEntries() const { return m_Entries; } + void removeObject(LLDerenderEntry::EEntryType eType, const LLUUID& idObject); + void removeObjects(LLDerenderEntry::EEntryType eType, const uuid_vec_t& idsObject); +protected: + entry_list_t::iterator findEntry(LLDerenderEntry::EEntryType eType, const LLUUID& idEntry); + entry_list_t::iterator findObjectEntry(U64 idRegion, const LLUUID& idObject, U32 idRootLocal); + + /* + * Object helper functions + */ +public: + bool addSelection(bool fPersist, std::vector<LLUUID>* pIdList = NULL); + static bool canAdd(const LLViewerObject* pObj); + static bool canAddSelection(); + bool processObjectUpdate(U64 idRegion, const LLUUID& idObject, const LLVOCacheEntry* pEntry); + bool processObjectUpdate(U64 idRegion, const LLUUID& idObject, U32 idObjectLocal, U32 idRootLocal); + bool processObjectUpdate(U64 idRegion, const LLUUID& idObject, U32 idObjectLocal, const U8* pBuffer); +protected: + LLDerenderObject* getObjectEntry(const LLUUID& idObject) /*const*/; + LLDerenderObject* getObjectEntry(U64 idRegion, const LLUUID& idObject, U32 idRootLocal) /*const*/; + bool isDerendered(const LLUUID& idObject) /*const*/ { return getObjectEntry(idObject) != NULL; } + bool isDerendered(U64 idRegion, const LLUUID& idObject, U32 idRootLocal) /*const*/ { return getObjectEntry(idRegion, idObject, idRootLocal) != NULL; } + + /* + * Static member functions + */ +public: + typedef boost::signals2::signal<void()> change_signal_t; + static boost::signals2::connection setChangeCallback(const change_signal_t::slot_type& cb) { return s_ChangeSignal.connect(cb); } + +protected: + entry_list_t m_Entries; + + static change_signal_t s_ChangeSignal; + static std::string s_PersistFilename; +}; + +// ============================================================================ + +#endif // LL_DERENDERLIST_H diff --git a/indra/newview/llfloaterblocked.cpp b/indra/newview/llfloaterblocked.cpp new file mode 100644 index 00000000000..4b06b385014 --- /dev/null +++ b/indra/newview/llfloaterblocked.cpp @@ -0,0 +1,791 @@ +/** + * + * Copyright (c) 2012-2017, Kitty Barnett + * + * The source code in this file is provided to you under the terms of the + * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt + * + * By copying, modifying or distributing this software, you acknowledge that + * you have read and understood your obligations described above, and agree to + * abide by those obligations. + * + */ + +#include "llviewerprecompiledheaders.h" + +#include "llavatarname.h" +#include "llavatarnamecache.h" +#include "llcallbacklist.h" +#include "llderenderlist.h" +#include "llfiltereditor.h" +#include "llfloateravatarpicker.h" +#include "llfloaterblocked.h" +#include "llfloaterreg.h" +#include "lllistcontextmenu.h" +#include "llmenugl.h" +#include "llnamelistctrl.h" +#include "llnotificationsutil.h" +#include "llpanelblockedlist.h" +#include "llscrolllistctrl.h" +#include "lltabcontainer.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llviewermenu.h" +#include "llviewerobjectlist.h" +#include "llvoavatar.h" + +#include <boost/algorithm/string.hpp> + +// ============================================================================ +// Constants +// + +const std::string BLOCKED_PARAM_NAME = "blocked_to_select"; +const std::string DERENDER_PARAM_NAME = "derender_to_select"; +const std::string EXCEPTION_PARAM_NAME = "exception_to_select"; +const std::string BLOCKED_TAB_NAME = "mute_tab"; +const std::string DERENDER_TAB_NAME = "derender_tab"; +const std::string EXCEPTION_TAB_NAME = "avatar_rendering_tab"; + +// ============================================================================ +// LLPanelBlockList +// + +static LLPanelInjector<LLPanelBlockList> t_panel_blocked_list("panel_block_list"); + +LLPanelBlockList::LLPanelBlockList() + : LLPanel() +{ + mCommitCallbackRegistrar.add("Block.AddAvatar", boost::bind(&LLPanelBlockList::onAddAvatar, this, _1)); + mCommitCallbackRegistrar.add("Block.AddByName", boost::bind(&LLPanelBlockList::onAddByName)); + mCommitCallbackRegistrar.add("Block.Remove", boost::bind(&LLPanelBlockList::onRemoveSelection, this)); +} + +LLPanelBlockList::~LLPanelBlockList() +{ + LLMuteList::getInstance()->removeObserver(this); +} + +// virtual +BOOL LLPanelBlockList::postBuild() +{ + setVisibleCallback(boost::bind(&LLPanelBlockList::removePicker, this)); + + m_pBlockList = findChild<LLScrollListCtrl>("block_list"); + m_pBlockList->setCommitOnDelete(true); + m_pBlockList->setCommitOnSelectionChange(true); + m_pBlockList->setCommitCallback(boost::bind(&LLPanelBlockList::onSelectionChange, this)); + + // Restore last sort order + if (U32 nSortValue = gSavedSettings.getU32("BlockMuteSortOrder")) + m_pBlockList->sortByColumnIndex(nSortValue >> 4, nSortValue & 0xF); + m_pBlockList->setSortChangedCallback(boost::bind(&LLPanelBlockList::onColumnSortChange, this)); + + m_pTrashBtn = findChild<LLButton>("block_trash_btn"); + + LLMuteList::getInstance()->addObserver(this); + + return TRUE; +} + +// virtual +void LLPanelBlockList::onOpen(const LLSD& sdParam) +{ + refresh(); + + if ( (sdParam.has(BLOCKED_PARAM_NAME)) && (sdParam[BLOCKED_PARAM_NAME].asUUID().notNull()) ) + { + LLMute muteEntry(sdParam[BLOCKED_PARAM_NAME].asUUID()); + selectEntry(muteEntry); + } +} + +void LLPanelBlockList::refresh() +{ + const LLSD& sdSel = m_pBlockList->getSelectedValue(); + + LLSD sdGenericRow; LLSD& sdGenericColumns = sdGenericRow["columns"]; + sdGenericColumns[0]["column"] = "item_name"; sdGenericColumns[0]["type"] = "text"; + sdGenericColumns[1]["column"] = "item_type"; sdGenericColumns[1]["type"] = "text"; + + LLSD sdAgentRow(sdGenericRow); LLSD& sdAgentColumns = sdAgentRow["columns"]; + sdAgentColumns[2]["column"] = "item_text"; sdAgentColumns[2]["type"] = "checkbox"; + sdAgentColumns[3]["column"] = "item_voice"; sdAgentColumns[3]["type"] = "checkbox"; + sdAgentColumns[4]["column"] = "item_particles"; sdAgentColumns[4]["type"] = "checkbox"; + sdAgentColumns[5]["column"] = "item_sounds"; sdAgentColumns[5]["type"] = "checkbox"; + + m_pBlockList->deleteAllItems(); + const std::vector<LLMute> muteEntries = LLMuteList::getInstance()->getMutes(); + for (const LLMute& muteEntry : muteEntries) + { + if ( (!m_strFilter.empty()) && (!boost::icontains(muteEntry.mName, m_strFilter)) ) + continue; + + switch (muteEntry.mType) + { + case LLMute::AGENT: + { + sdAgentRow["value"] = LLSD().with("id", muteEntry.mID).with("name", muteEntry.mName); + sdAgentColumns[0]["value"] = muteEntry.mName; + sdAgentColumns[1]["value"] = muteEntry.getDisplayType(); + sdAgentColumns[2]["value"] = (muteEntry.mFlags & LLMute::flagTextChat) == 0; + sdAgentColumns[3]["value"] = (muteEntry.mFlags & LLMute::flagVoiceChat) == 0; + sdAgentColumns[4]["value"] = (muteEntry.mFlags & LLMute::flagParticles) == 0; + sdAgentColumns[5]["value"] = (muteEntry.mFlags & LLMute::flagObjectSounds) == 0; + m_pBlockList->addElement(sdAgentRow, boost::bind(&LLPanelBlockList::onToggleMuteFlag, this, _1, _2), ADD_BOTTOM); + } + break; + default: + { + sdGenericRow["value"] = LLSD().with("id", muteEntry.mID).with("name", muteEntry.mName); + sdGenericColumns[0]["value"] = muteEntry.mName; + sdGenericColumns[1]["value"] = muteEntry.getDisplayType(); + m_pBlockList->addElement(sdGenericRow, ADD_BOTTOM); + } + break; + } + } + selectEntry(sdSel); +} + +void LLPanelBlockList::removePicker() +{ + if (m_hPicker.get()) + { + m_hPicker.get()->closeFloater(); + } +} + +void LLPanelBlockList::selectEntry(const LLMute& muteEntry) +{ + const std::vector<LLScrollListItem*> muteItems = m_pBlockList->getAllData(); + for (auto itItem = muteItems.begin(); itItem != muteItems.end(); ++itItem) + { + const LLSD& sdValue = (*itItem)->getValue(); + if ( (muteEntry.mID == sdValue["id"].asUUID()) && ((muteEntry.mName.empty()) ||(muteEntry.mName == sdValue["name"].asString())) ) + { + S32 idxItem = itItem - muteItems.begin(); + if (idxItem != m_pBlockList->getFirstSelectedIndex()) + { + m_pBlockList->deselectAllItems(); + m_pBlockList->selectNthItem(idxItem); + break; + } + } + } +} + +void LLPanelBlockList::setFilterString(const std::string& strFilter) +{ + m_strFilter = strFilter; + refresh(); +} + +void LLPanelBlockList::updateButtons() +{ + bool fHasSelection = (nullptr != m_pBlockList->getFirstSelected()); + m_pTrashBtn->setEnabled(fHasSelection); +} + +void LLPanelBlockList::onChange() +{ + if (m_fRefreshOnChange) + { + refresh(); + } +} + +void LLPanelBlockList::onAddAvatar(LLUICtrl* pCtrl) +{ + if (!m_hPicker.isDead()) + { + m_hPicker.get()->setVisibleAndFrontmost(true); + return; + } + + if (LLFloater* pRootFloater = gFloaterView->getParentFloater(pCtrl)) + { + LLFloaterAvatarPicker* pPicker = LLFloaterAvatarPicker::show( + boost::bind(&LLPanelBlockList::onAddAvatarCallback, _1, _2), + false /*allow_multiple*/, true /*close_on_select*/, false /*skip_agent*/, pRootFloater->getName(), pCtrl); + pRootFloater->addDependentFloater(pPicker); + m_hPicker = pPicker->getHandle(); + } +} + +// static +void LLPanelBlockList::onAddAvatarCallback(const uuid_vec_t& idAgents, const std::vector<LLAvatarName>& avAgents) +{ + if ( (idAgents.empty()) || (avAgents.empty()) ) + { + return; + } + + LLMute mute(idAgents[0], avAgents[0].getLegacyName(), LLMute::AGENT); + if (LLMuteList::getInstance()->add(mute)) + { + LLFloaterBlocked::showMuteAndSelect(mute.mID); + } +} + +// static +void LLPanelBlockList::onAddByName() +{ + LLFloaterGetBlockedObjectName::show(&LLPanelBlockList::onAddByNameCallback); +} + +// static +void LLPanelBlockList::onAddByNameCallback(const std::string& strBlockName) +{ + if (strBlockName.empty()) + { + return; + } + + LLMute mute(LLUUID::null, strBlockName, LLMute::BY_NAME); + if (!LLMuteList::getInstance()->add(mute)) + { + LLNotificationsUtil::add("MuteByNameFailed"); + } +} + +void LLPanelBlockList::onRemoveSelection() +{ + m_fRefreshOnChange = false; + + std::vector<LLScrollListItem*> selItems = m_pBlockList->getAllSelected(); + for (std::vector<LLScrollListItem*>::iterator itItem = selItems.begin(); itItem != selItems.end(); ++itItem) + { + LLScrollListItem* pSelItem = *itItem; const LLSD sdValue = pSelItem->getValue(); + + LLMute selMute(sdValue["id"].asUUID(), sdValue["name"].asString()); + if (LLMuteList::getInstance()->remove(selMute)) + { + m_pBlockList->deleteSingleItem(pSelItem); + } + } + + m_fRefreshOnChange = true; +} + +void LLPanelBlockList::onColumnSortChange() +{ + U32 nSortValue = 0; + + S32 idxColumn = m_pBlockList->getSortColumnIndex(); + if (-1 != idxColumn) + { + nSortValue = idxColumn << 4 | ((m_pBlockList->getSortAscending()) ? 1 : 0); + } + + gSavedSettings.setU32("BlockMuteSortOrder", nSortValue); +} + +void LLPanelBlockList::onIdleRefresh(LLHandle<LLPanel> hPanel) +{ + if (!hPanel.isDead()) + { + ((LLPanelBlockList*)hPanel.get())->refresh(); + } +} + +void LLPanelBlockList::onSelectionChange() +{ + updateButtons(); +} + +void LLPanelBlockList::onToggleMuteFlag(const LLSD& sdValue, const LLScrollListCell* pCell) +{ + if (!pCell) + return; + + LLMute muteEntry(sdValue["id"].asUUID(), sdValue["name"].asString(), LLMute::AGENT); U32 muteFlag = 0; + + const std::string& strColumnName = pCell->getColumnName(); + if ("item_text" == strColumnName) + muteFlag = LLMute::flagTextChat; + else if ("item_voice" == strColumnName) + muteFlag = LLMute::flagVoiceChat; + else if ("item_particles" == strColumnName) + muteFlag = LLMute::flagParticles; + else if ("item_sounds" == strColumnName) + muteFlag = LLMute::flagObjectSounds; + + if (muteFlag) + { + m_fRefreshOnChange = false; + if (pCell->getValue().asBoolean()) + LLMuteList::getInstance()->add(muteEntry, muteFlag); + else + LLMuteList::getInstance()->remove(muteEntry, muteFlag); + m_fRefreshOnChange = true; + + selectEntry(muteEntry); + + // Refreshing now will invalidate an iterator upstream so do it on the next idle tick + doOnIdleOneTime(boost::bind(&LLPanelBlockList::onIdleRefresh, getHandle())); + } +} + +// ============================================================================ +// LLPanelDerenderList +// + +static LLPanelInjector<LLPanelDerenderList> t_panel_derender_list("panel_derender_list"); + +LLPanelDerenderList::LLPanelDerenderList() + : LLPanel() + , m_pDerenderList(NULL) +{ +} + +LLPanelDerenderList::~LLPanelDerenderList() +{ + m_DerenderChangeConn.disconnect(); +} + +BOOL LLPanelDerenderList::postBuild() +{ + m_pDerenderList = findChild<LLScrollListCtrl>("derender_list"); + m_pDerenderList->setCommitCallback(boost::bind(&LLPanelDerenderList::onSelectionChange, this)); + m_pDerenderList->setCommitOnDelete(true); + m_pDerenderList->setCommitOnSelectionChange(true); + + // Restore last sort order + U32 nSortValue = gSavedSettings.getU32("BlockDerenderSortOrder"); + if (nSortValue) + { + m_pDerenderList->sortByColumnIndex(nSortValue >> 4, nSortValue & 0xF); + } + m_pDerenderList->setSortChangedCallback(boost::bind(&LLPanelDerenderList::onColumnSortChange, this)); + + m_DerenderChangeConn = LLDerenderList::setChangeCallback(boost::bind(&LLPanelDerenderList::refresh, this)); + findChild<LLUICtrl>("derender_trash_btn")->setCommitCallback(boost::bind(&LLPanelDerenderList::onSelectionRemove, this)); + + return TRUE; +} + +void LLPanelDerenderList::onOpen(const LLSD& sdParam) +{ + refresh(); + + if ( (sdParam.has(DERENDER_PARAM_NAME)) && (sdParam[DERENDER_PARAM_NAME].asUUID().notNull()) ) + { + m_pDerenderList->selectByID(sdParam[DERENDER_PARAM_NAME].asUUID()); + } +} + +void LLPanelDerenderList::onColumnSortChange() +{ + U32 nSortValue = 0; + + S32 idxColumn = m_pDerenderList->getSortColumnIndex(); + if (-1 != idxColumn) + { + nSortValue = idxColumn << 4 | ((m_pDerenderList->getSortAscending()) ? 1 : 0); + } + + gSavedSettings.setU32("BlockDerenderSortOrder", nSortValue); +} + +void LLPanelDerenderList::onSelectionChange() +{ + bool hasSelected = (NULL != m_pDerenderList->getFirstSelected()); + getChildView("derender_trash_btn")->setEnabled(hasSelected); +} + +void LLPanelDerenderList::onSelectionRemove() +{ + std::vector<LLScrollListItem*> selItems = m_pDerenderList->getAllSelected(); uuid_vec_t idsObject; +// std::for_each(selItems.begin(), selItems.end(), [&idsObject](const LLScrollListItem* i) { idsObject.push_back(i->getValue().asUUID()); }); + for (std::vector<LLScrollListItem*>::iterator itItem = selItems.begin(); itItem != selItems.end(); ++itItem) + { + idsObject.push_back((*itItem)->getValue().asUUID()); + } + + LLDerenderList::instance().removeObjects(LLDerenderEntry::TYPE_OBJECT, idsObject); +} + +void LLPanelDerenderList::refresh() +{ + m_pDerenderList->clearRows(); + if (LLDerenderList::instanceExists()) + { + LLSD sdRow; LLSD& sdColumns = sdRow["columns"]; + sdColumns[0]["column"] = "object_name"; sdColumns[0]["type"] = "text"; + sdColumns[1]["column"] = "location"; sdColumns[1]["type"] = "text"; + sdColumns[2]["column"] = "derender_type"; sdColumns[2]["type"] = "text"; + + for (const auto& pEntry : LLDerenderList::instance().getEntries()) + { + sdRow["value"] = pEntry->getID(); + sdColumns[0]["value"] = pEntry->getName(); + if (LLDerenderEntry::TYPE_OBJECT == pEntry->getType()) + { + auto pObjEntry = static_cast<LLDerenderObject*>(pEntry.get()); + sdColumns[1]["value"] = fmt::format(FMT_STRING("{} <{}, {}, {}>"), pObjEntry->strRegionName, ll_round(pObjEntry->posRegion.mV[VX]), ll_round(pObjEntry->posRegion.mV[VY]), ll_round(pObjEntry->posRegion.mV[VZ])); + } + sdColumns[2]["value"] = (pEntry->isPersistent()) ? "Permanent" : "Temporary"; + + m_pDerenderList->addElement(sdRow, ADD_BOTTOM); + } + } +} + +// ============================================================================ +// LLPanelAvatarRendering - Menu helper class +// + +class LLPanelAvatarRenderingContextMenu : public LLListContextMenu +{ +public: + LLPanelAvatarRenderingContextMenu(LLPanelAvatarRendering* pAvRenderingPanel) + : m_pAvRenderingPanel(pAvRenderingPanel) + { + } + +protected: + LLContextMenu* createMenu() override + { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("Settings.SetRendering", boost::bind(&LLPanelAvatarRendering::onSetException, m_pAvRenderingPanel, mUUIDs.front(), _2)); + + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + enable_registrar.add("Settings.IsSelected", boost::bind(&LLPanelAvatarRendering::onHasException, m_pAvRenderingPanel, mUUIDs.front(), _2)); + + LLContextMenu* pMenu = createFromFile("menu_avatar_rendering_settings.xml"); + return pMenu; + } + +protected: + LLPanelAvatarRendering* m_pAvRenderingPanel; +}; + +// ============================================================================ +// LLPanelAvatarRendering - Helper functions +// + +static std::string createTimestamp(S32 datetime) +{ + std::string timeStr = "[" + LLTrans::getString("TimeMonth") + "]/[" + LLTrans::getString("TimeDay") + "]/[" + LLTrans::getString("TimeYear") + "]"; + LLStringUtil::format(timeStr, LLSD().with("datetime", datetime)); + return timeStr; +} + +static LLVOAvatar* findAvatar(const LLUUID& idAgent) +{ + LLViewerObject* pAvObj = gObjectList.findObject(idAgent); + while ( (pAvObj) && (pAvObj->isAttachment()) ) + pAvObj = (LLViewerObject*)pAvObj->getParent(); + + if ((pAvObj) && (pAvObj->isAvatar()) ) + return (LLVOAvatar*)pAvObj; + return nullptr; +} + +static void setAvatarRenderSetting(const LLUUID& idAgent, LLVOAvatar::VisualMuteSettings eSetting) +{ + if (LLVOAvatar* pAvatar = findAvatar(idAgent)) + pAvatar->setVisualMuteSettings(LLVOAvatar::VisualMuteSettings(eSetting)); + else + LLRenderMuteList::getInstance()->saveVisualMuteSetting(idAgent, eSetting); +} + +// ============================================================================ +// LLPanelAvatarRendering - Configure avatar complexity excpetions +// + +static LLPanelInjector<LLPanelAvatarRendering> t_panel_block_avatar_rendering("panel_block_avatar_rendering"); + +LLPanelAvatarRendering::LLPanelAvatarRendering() + : LLPanel() +{ + mCommitCallbackRegistrar.add("Rendering.AddException", boost::bind(&LLPanelAvatarRendering::onAddException, this, _1, _2)); + mCommitCallbackRegistrar.add("Rendering.RemoveException", boost::bind(&LLPanelAvatarRendering::onRemoveException, this)); +} + +LLPanelAvatarRendering::~LLPanelAvatarRendering() +{ + delete m_pContextMenu; + LLRenderMuteList::getInstance()->removeObserver(this); +} + +// virtual +BOOL LLPanelAvatarRendering::postBuild() +{ + setVisibleCallback(boost::bind(&LLPanelAvatarRendering::removePicker, this)); + + m_pExceptionList = findChild<LLNameListCtrl>("exception_list"); + m_pExceptionList->setCommitOnDelete(true); + m_pExceptionList->setCommitOnSelectionChange(true); + m_pExceptionList->setCommitCallback(boost::bind(&LLPanelAvatarRendering::onSelectionChange, this)); + m_pExceptionList->setRightMouseDownCallback(boost::bind(&LLPanelAvatarRendering::onExceptionMenu, this, _2, _3)); + + // Restore last sort order + if (U32 nSortValue = gSavedSettings.getU32("BlockRenderingSortOrder")) + m_pExceptionList->sortByColumnIndex(nSortValue >> 4, nSortValue & 0xF); + m_pExceptionList->setSortChangedCallback(boost::bind(&LLPanelAvatarRendering::onColumnSortChange, this)); + + m_pTrashBtn = findChild<LLButton>("rendering_exception_trash_btn"); + + LLRenderMuteList::getInstance()->addObserver(this); + m_pContextMenu = new LLPanelAvatarRenderingContextMenu(this); + + return TRUE; +} + +// virtual +void LLPanelAvatarRendering::onOpen(const LLSD& sdParam) +{ + refresh(); + + if ((sdParam.has(EXCEPTION_PARAM_NAME)) && (sdParam[EXCEPTION_PARAM_NAME].asUUID().notNull())) + { + m_pExceptionList->selectByID(sdParam[EXCEPTION_PARAM_NAME].asUUID()); + } +} + +void LLPanelAvatarRendering::refresh() +{ + const LLUUID idSel = m_pExceptionList->getSelectedValue().asUUID(); + + m_pExceptionList->deleteAllItems(); + + LLAvatarName avName; LLNameListCtrl::NameItem paramItem; + for (const auto& kvEntry : LLRenderMuteList::getInstance()->sVisuallyMuteSettingsMap) + { + if ( (!LLAvatarNameCache::get(kvEntry.first, &avName)) || ((!m_strFilter.empty()) && (!boost::icontains(avName.getCompleteName(), m_strFilter))) ) + continue; + + paramItem.value = kvEntry.first; + paramItem.columns.add().value(avName.getCompleteName()).column("name"); + paramItem.columns.add().value(getString(kvEntry.second == 1 ? "av_never_render" : "av_always_render")).column("setting"); + paramItem.columns.add().value(createTimestamp(LLRenderMuteList::getInstance()->getVisualMuteDate(kvEntry.first))).column("timestamp"); + m_pExceptionList->addNameItemRow(paramItem); + } + + if (idSel.notNull()) + { + m_pExceptionList->selectByID(idSel); + } +} + +void LLPanelAvatarRendering::removePicker() +{ + if (m_hPicker.get()) + { + m_hPicker.get()->closeFloater(); + } +} + +void LLPanelAvatarRendering::setFilterString(const std::string& strFilter) +{ + m_strFilter = strFilter; + refresh(); +} + +void LLPanelAvatarRendering::updateButtons() +{ + bool fHasSelection = (nullptr != m_pExceptionList->getFirstSelected()); + m_pTrashBtn->setEnabled(fHasSelection); +} + +void LLPanelAvatarRendering::onChange() +{ + if (m_fRefreshOnChange) + { + refresh(); + } +} + +void LLPanelAvatarRendering::onAddException(LLUICtrl* pCtrl, const LLSD& sdParam) +{ + const std::string strParam = sdParam.asString(); + + LLVOAvatar::VisualMuteSettings eSetting = (LLVOAvatar::VisualMuteSettings)0; + if ("never" == strParam) + eSetting = LLVOAvatar::AV_DO_NOT_RENDER; + else if ("always" == strParam) + eSetting = LLVOAvatar::AV_ALWAYS_RENDER; + + if (LLFloater* pRootFloater = gFloaterView->getParentFloater(pCtrl)) + { + removePicker(); + + LLFloaterAvatarPicker* pPicker = LLFloaterAvatarPicker::show( + boost::bind(&LLPanelAvatarRendering::onAddExceptionCb, _1, eSetting), + false /*allow_multiple*/, true /*close_on_select*/, false /*skip_agent*/, pRootFloater->getName(), pCtrl); + pRootFloater->addDependentFloater(pPicker); + m_hPicker = pPicker->getHandle(); + } +} + +void LLPanelAvatarRendering::onAddExceptionCb(const uuid_vec_t& idAgents, S32 nSetting) +{ + if (idAgents.empty()) + return; + + for (const LLUUID& idAgent : idAgents) + { + setAvatarRenderSetting(idAgent, (LLVOAvatar::VisualMuteSettings)nSetting); + } + + LLFloaterBlocked::showRenderExceptionAndSelect(idAgents[0]); +} + +bool LLPanelAvatarRendering::onHasException(const LLUUID& idAgent, const LLSD& sdParamn) +{ + const std::string strParam = sdParamn.asString(); + + LLVOAvatar::VisualMuteSettings eSetting = (LLVOAvatar::VisualMuteSettings)LLRenderMuteList::getInstance()->getSavedVisualMuteSetting(idAgent); + if ("default" == strParam) + return (eSetting == LLVOAvatar::AV_RENDER_NORMALLY); + else if ("non_default" == strParam) + return (eSetting != LLVOAvatar::AV_RENDER_NORMALLY); + else if ("never" == strParam) + return (eSetting == LLVOAvatar::AV_DO_NOT_RENDER); + else if ("always" == strParam) + return (eSetting == LLVOAvatar::AV_ALWAYS_RENDER); + return false; +} + +void LLPanelAvatarRendering::onExceptionMenu(S32 x, S32 y) +{ + m_pExceptionList->selectItemAt(x, y, MASK_NONE); + + uuid_vec_t selected_uuids; + if (m_pExceptionList->getCurrentID().notNull()) + { + selected_uuids.push_back(m_pExceptionList->getCurrentID()); + m_pContextMenu->show(m_pExceptionList, selected_uuids, x, y); + } +} + +void LLPanelAvatarRendering::onRemoveException() +{ + m_fRefreshOnChange = false; + + const std::vector<LLScrollListItem*> selItems = m_pExceptionList->getAllSelected(); + for (auto* pSelItem : selItems) + { + const LLSD sdValue = pSelItem->getValue(); + if (sdValue.isUUID()) + { + setAvatarRenderSetting(sdValue.asUUID(), LLVOAvatar::AV_RENDER_NORMALLY); + m_pExceptionList->deleteSingleItem(pSelItem); + } + } + + m_fRefreshOnChange = true; +} + +void LLPanelAvatarRendering::onSetException(const LLUUID& idAgent, const LLSD& sdParamn) +{ + const std::string strParam = sdParamn.asString(); + + LLVOAvatar::VisualMuteSettings nSetting = (LLVOAvatar::VisualMuteSettings)0; + if ("default" == strParam) + nSetting = LLVOAvatar::AV_RENDER_NORMALLY; + else if ("never" == strParam) + nSetting = LLVOAvatar::AV_DO_NOT_RENDER; + else if ("always" == strParam) + nSetting = LLVOAvatar::AV_ALWAYS_RENDER; + + setAvatarRenderSetting(idAgent, nSetting); +} + +void LLPanelAvatarRendering::onColumnSortChange() +{ + U32 nSortValue = 0; + + S32 idxColumn = m_pExceptionList->getSortColumnIndex(); + if (-1 != idxColumn) + { + nSortValue = idxColumn << 4 | ((m_pExceptionList->getSortAscending()) ? 1 : 0); + } + + gSavedSettings.setU32("BlockRenderingSortOrder", nSortValue); +} + +void LLPanelAvatarRendering::onSelectionChange() +{ + updateButtons(); +} + +// ============================================================================ +// LLFloaterBlocked +// + +LLFloaterBlocked::LLFloaterBlocked(const LLSD& sdKey) + : LLFloater(sdKey) +{ +} + +LLFloaterBlocked::~LLFloaterBlocked() +{ +} + +BOOL LLFloaterBlocked::postBuild() +{ + m_pFilterEditor = findChild<LLFilterEditor>("blocked_filter"); + m_pFilterEditor->setCommitCallback(boost::bind(&LLFloaterBlocked::onFilterEdit, this, _2)); + + m_pBlockedTabs = findChild<LLTabContainer>("blocked_tabs"); + m_pBlockedTabs->setCommitCallback(boost::bind(&LLFloaterBlocked::onTabSelect, this, _2)); + + return TRUE; +} + +void LLFloaterBlocked::onOpen(const LLSD& sdParam) +{ + if (sdParam.has(BLOCKED_PARAM_NAME)) + m_pBlockedTabs->selectTabByName(BLOCKED_TAB_NAME); + else if (sdParam.has(DERENDER_PARAM_NAME)) + m_pBlockedTabs->selectTabByName(DERENDER_TAB_NAME); + if (sdParam.has(EXCEPTION_PARAM_NAME)) + m_pBlockedTabs->selectTabByName(EXCEPTION_TAB_NAME); + else if ( (sdParam.isString()) && (m_pBlockedTabs->hasChild(sdParam.asString())) ) + m_pBlockedTabs->selectTabByName(sdParam.asString()); + else + m_pBlockedTabs->getCurrentPanel()->onOpen(sdParam); + mKey.clear(); +} + +void LLFloaterBlocked::onFilterEdit(const std::string& strFilter) +{ + if (LLPanelBlockBase* pCurPanel = dynamic_cast<LLPanelBlockBase*>(m_pBlockedTabs->getCurrentPanel())) + { + pCurPanel->setFilterString(strFilter); + } +} + +void LLFloaterBlocked::onTabSelect(const LLSD& sdParam) +{ + LLPanel* pActivePanel = m_pBlockedTabs->getPanelByName(sdParam.asString()); + if (pActivePanel) + { + if (LLPanelBlockBase* pActivePanelBase = dynamic_cast<LLPanelBlockBase*>(pActivePanel)) + m_pFilterEditor->setText(pActivePanelBase->getFilterString()); + pActivePanel->onOpen(mKey); + } +} + +void LLFloaterBlocked::showMuteAndSelect(const LLUUID& idMute) +{ + LLFloaterReg::showInstance("blocked", LLSD().with(BLOCKED_PARAM_NAME, idMute)); +} + +void LLFloaterBlocked::showDerenderAndSelect(const LLUUID& idEntry) +{ + LLFloaterReg::showInstance("blocked", LLSD().with(DERENDER_PARAM_NAME, idEntry)); +} + +void LLFloaterBlocked::showRenderExceptionAndSelect(const LLUUID& idEntry) +{ + LLFloaterReg::showInstance("blocked", LLSD().with(EXCEPTION_PARAM_NAME, idEntry)); +} + +// ============================================================================ diff --git a/indra/newview/llfloaterblocked.h b/indra/newview/llfloaterblocked.h new file mode 100644 index 00000000000..23cc04bb347 --- /dev/null +++ b/indra/newview/llfloaterblocked.h @@ -0,0 +1,245 @@ +/** + * + * Copyright (c) 2012-2017, Kitty Barnett + * + * The source code in this file is provided to you under the terms of the + * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt + * + * By copying, modifying or distributing this software, you acknowledge that + * you have read and understood your obligations described above, and agree to + * abide by those obligations. + * + */ + +#pragma once + +#include "llavatarname.h" +#include "llfloater.h" +#include "llmutelist.h" + +class LLFilterEditor; +class LLListContextMenu; +class LLNameListCtrl; +class LLScrollListCell; +class LLScrollListCtrl; +class LLTabContainer; + +// ============================================================================ +// Constants +// + +extern const std::string BLOCKED_PARAM_NAME; +extern const std::string DERENDER_PARAM_NAME; +extern const std::string EXCEPTION_PARAM_NAME; +extern const std::string BLOCKED_TAB_NAME; +extern const std::string DERENDER_TAB_NAME; +extern const std::string EXCEPTION_TAB_NAME; + +// ============================================================================ +// LLPanelBlockBase +// + +class LLPanelBlockBase +{ +public: + virtual const std::string& getFilterString() const = 0; + virtual void setFilterString(const std::string& strFilter) = 0; +}; + +// ============================================================================ +// LLPanelBlockList +// + +class LLPanelBlockList : public LLPanel, public LLMuteListObserver, public LLPanelBlockBase +{ +public: + LLPanelBlockList(); + ~LLPanelBlockList(); + + /* + * LLPanel overrides + */ +public: + BOOL postBuild() override; + void onOpen(const LLSD& sdParam) override; + + /* + * Member functions + */ +public: + const std::string& getFilterString() const override { return m_strFilter; } + void setFilterString(const std::string& strFilter) override; +protected: + void refresh(); + void removePicker(); + void selectEntry(const LLSD& sdValue) { LLMute muteEntry(sdValue["id"].asUUID(), sdValue["name"].asString()); selectEntry(muteEntry); } + void selectEntry(const LLMute& muteEntry); + void updateButtons(); + + /* + * Event handlers + */ +public: + void onChange() override; +protected: + void onAddAvatar(LLUICtrl* pCtrl); + static void onAddAvatarCallback(const uuid_vec_t& idAgents, const std::vector<LLAvatarName>& avAgents); + static void onAddByName(); + static void onAddByNameCallback(const std::string& strBlockName); + void onRemoveSelection(); + void onColumnSortChange(); + static void onIdleRefresh(LLHandle<LLPanel> hPanel); + void onSelectionChange(); + void onToggleMuteFlag(const LLSD& sdValue, const LLScrollListCell* pCell); + + /* + * Member variables + */ +protected: + bool m_fRefreshOnChange = true; + std::string m_strFilter; + LLScrollListCtrl* m_pBlockList = nullptr; + LLButton* m_pTrashBtn = nullptr; + LLHandle<LLFloater> m_hPicker; +}; + +// ============================================================================ +// LLPanelDerenderList +// + +class LLPanelDerenderList : public LLPanel +{ +public: + LLPanelDerenderList(); + ~LLPanelDerenderList(); + + /* + * LLPanel overrides + */ +public: + BOOL postBuild() override; + void onOpen(const LLSD& sdParam) override; + + /* + * Member functions + */ +protected: + void refresh(); + + /* + * Event handlers + */ +protected: + void onColumnSortChange(); + void onSelectionChange(); + void onSelectionRemove(); + + /* + * Member variables + */ +protected: + LLScrollListCtrl* m_pDerenderList; + boost::signals2::connection m_DerenderChangeConn; +}; + +// ============================================================================ +// LLPanelAvatarRendering - Configure avatar complexity excpetions +// + +class LLPanelAvatarRendering : public LLPanel, public LLMuteListObserver, public LLPanelBlockBase +{ + friend class LLPanelAvatarRenderingContextMenu; +public: + LLPanelAvatarRendering(); + ~LLPanelAvatarRendering(); + + /* + * LLPanel overrides + */ +public: + BOOL postBuild() override; + void onOpen(const LLSD& sdParam) override; + + /* + * Member functions + */ +public: + const std::string& getFilterString() const override { return m_strFilter; } + void setFilterString(const std::string& strFilter) override; +protected: + void refresh(); + void removePicker(); + void updateButtons(); + + /* + * Event handlers + */ +public: + void onChange() override; +protected: + void onAddException(LLUICtrl* pCtrl, const LLSD& sdParam); + static void onAddExceptionCb(const uuid_vec_t& idAgents, S32 nSetting); + bool onHasException(const LLUUID& idAgent, const LLSD& sdParamn); + void onExceptionMenu(S32 x, S32 y); + void onRemoveException(); + void onSetException(const LLUUID& idAgent, const LLSD& sdParamn); + + void onColumnSortChange(); + void onSelectionChange(); + + /* + * Member variables + */ +protected: + bool m_fRefreshOnChange = true; + std::string m_strFilter; + LLNameListCtrl* m_pExceptionList = nullptr; + LLButton* m_pTrashBtn = nullptr; + LLListContextMenu* m_pContextMenu = nullptr; + LLHandle<LLFloater> m_hPicker; +}; + +// ============================================================================ +// LLFloaterBlocked +// + +class LLFloaterBlocked : public LLFloater +{ +public: + LLFloaterBlocked(const LLSD& sdKey); + ~LLFloaterBlocked(); + + /* + * LLFloater overrides + */ +public: + BOOL postBuild() override; + void onOpen(const LLSD& sdParam) override; + + /* + * Event handlers + */ +protected: + void onFilterEdit(const std::string& strFilter); + void onTabSelect(const LLSD& sdParam); + + /* + * Member functions + */ +public: + static void showMuteAndSelect(const LLUUID& idMute); + static void showDerenderAndSelect(const LLUUID& idEntry); + static void showRenderExceptionAndSelect(const LLUUID& idEntry); + + /* + * Member variables + */ +protected: + LLFilterEditor* m_pFilterEditor = nullptr; + LLTabContainer* m_pBlockedTabs = nullptr; +}; + +// ============================================================================ diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp index f9c9ad91215..b096dba0773 100644 --- a/indra/newview/llfloaterbump.cpp +++ b/indra/newview/llfloaterbump.cpp @@ -36,7 +36,8 @@ #include "llfloaterreg.h" #include "llfloaterreporter.h" #include "llmutelist.h" -#include "llpanelblockedlist.h" +#include "llfloaterblocked.h" +//#include "llpanelblockedlist.h" #include "llscrolllistctrl.h" #include "lltrans.h" #include "lluictrlfactory.h" @@ -245,7 +246,8 @@ void LLFloaterBump::muteAvatar() else { LLMuteList::getInstance()->add(mute); - LLPanelBlockedList::showPanelAndSelect(mute.mID); + LLFloaterBlocked::showMuteAndSelect(mute.mID); + //LLPanelBlockedList::showPanelAndSelect(mute.mID); } } diff --git a/indra/newview/llfloaterperformance.cpp b/indra/newview/llfloaterperformance.cpp index 74ecdb4a4b9..57f030da78c 100644 --- a/indra/newview/llfloaterperformance.cpp +++ b/indra/newview/llfloaterperformance.cpp @@ -564,7 +564,7 @@ void LLFloaterPerformance::onClickHideAvatars() void LLFloaterPerformance::onClickExceptions() { - LLFloaterReg::showInstance("avatar_render_settings"); + LLFloaterReg::showInstance("blocked", LLSD("avatar_rendering_tab")); } void LLFloaterPerformance::updateMaxRenderTime() diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 39ecf87aa54..46dc4e961e7 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -2081,8 +2081,11 @@ void LLFloaterPreference::onChangeAnimationFolder() // but the UI for this will still be enabled void LLFloaterPreference::onClickBlockList() { - LLFloaterSidePanelContainer::showPanel("people", "panel_people", - LLSD().with("people_panel_tab_name", "blocked_panel")); +// [SL:KB] - Patch: World-Derender | Checked: Catznip-3.2 + LLFloaterReg::showInstance("blocked"); +// [/SL:KB] +// LLFloaterSidePanelContainer::showPanel("people", "panel_people", +// LLSD().with("people_panel_tab_name", "blocked_panel")); } void LLFloaterPreference::onClickProxySettings() @@ -2107,7 +2110,7 @@ void LLFloaterPreference::onClickSpellChecker() void LLFloaterPreference::onClickRenderExceptions() { - LLFloaterReg::showInstance("avatar_render_settings"); + LLFloaterReg::showInstance("blocked", LLSD("avatar_rendering_tab")); } void LLFloaterPreference::onClickAutoAdjustments() diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index 038bd331c1f..f75554bb934 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -175,6 +175,18 @@ void LLFloaterSidePanelContainer::showPanel(std::string_view floater_name, const void LLFloaterSidePanelContainer::showPanel(std::string_view floater_name, std::string_view panel_name, const LLSD& key) { +// [SL:KB] - Patch: World-Derender | Checked: Catznip-3.2 + // Hack in case we forget a reference somewhere + if ( (!panel_name.empty()) && ("panel_people" == panel_name) && (key.has("people_panel_tab_name")) && ("blocked_panel" == key["people_panel_tab_name"].asString()) ) + { +#ifndef LL_RELEASE_FOR_DOWNLOAD + LL_ERRS() << "Request to open the blocked floater through the sidepanel!" << LL_ENDL; +#endif // LL_RELEASE_FOR_DOWNLOAD + LLFloaterReg::showInstance("blocked", key); + return; + } +// [/SL:KB] + LLFloaterSidePanelContainer* floaterp = LLFloaterReg::getTypedInstance<LLFloaterSidePanelContainer>(floater_name); // if (floaterp) // [RLVa:KB] - Checked: 2013-04-16 (RLVa-1.4.8) diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp index da3ed9ebbfd..3f5b19eacd4 100644 --- a/indra/newview/llinspectremoteobject.cpp +++ b/indra/newview/llinspectremoteobject.cpp @@ -29,7 +29,8 @@ #include "llinspectremoteobject.h" #include "llinspect.h" #include "llmutelist.h" -#include "llpanelblockedlist.h" +#include "llfloaterblocked.h" +//#include "llpanelblockedlist.h" #include "llslurl.h" #include "lltrans.h" #include "llui.h" @@ -138,7 +139,8 @@ void LLInspectRemoteObject::onClickBlock() { LLMute mute(mObjectID, mName, LLMute::OBJECT); LLMuteList::getInstance()->add(mute); - LLPanelBlockedList::showPanelAndSelect(mute.mID); + LLFloaterBlocked::showMuteAndSelect(mute.mID); + //LLPanelBlockedList::showPanelAndSelect(mute.mID); closeFloater(); } diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 23c49a80de2..f1052dc1952 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -333,6 +333,16 @@ LLScrollListItem* LLNameListCtrl::addElement(const LLSD& element, EAddPosition p return addNameItemRow(item_params, pos); } +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 +LLScrollListItem* LLNameListCtrl::addElement(const LLSD& element, const LLScrollListItem::commit_signal_t::slot_type& cb, EAddPosition pos) +{ + LLNameListCtrl::NameItem item_params; + LLParamSDParser parser; + parser.readSD(element, item_params); + item_params.commit_callback = cb; + return addNameItemRow(item_params, pos); +} +// [/SL:KB] LLScrollListItem* LLNameListCtrl::addNameItemRow( const LLNameListCtrl::NameItem& name_item, diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 4a4bd4ba09f..fd8e62224a0 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -147,7 +147,11 @@ class LLNameListCtrl BOOL enabled = TRUE, const std::string& suffix = LLStringUtil::null, const std::string& prefix = LLStringUtil::null); LLScrollListItem* addNameItem(NameItem& item, EAddPosition pos = ADD_BOTTOM); - /*virtual*/ LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); +// /*virtual*/ LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); +// [SL:KB] - Patch: Control-ScrollList | Checked: Catznip-5.2 + LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = nullptr) override; + LLScrollListItem* addElement(const LLSD& element, const LLScrollListItem::commit_signal_t::slot_type& cb, EAddPosition pos = ADD_BOTTOM) override; +// [/SL:KB] LLScrollListItem* addNameItemRow(const NameItem& value, EAddPosition pos = ADD_BOTTOM, const std::string& suffix = LLStringUtil::null, const std::string& prefix = LLStringUtil::null); diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index e6aff67734e..f2a82112fc2 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -48,6 +48,8 @@ #include "llsidetraypanelcontainer.h" #include "llviewercontrol.h" +#if 0 + static LLPanelInjector<LLPanelBlockedList> t_panel_blocked_list("panel_block_list_sidetray"); // @@ -256,6 +258,8 @@ void LLPanelBlockedList::callbackBlockByName(const std::string& text) } } +#endif + ////////////////////////////////////////////////////////////////////////// // LLFloaterGetBlockedObjectName ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h index 8339cf16b3a..8ec05e04c70 100644 --- a/indra/newview/llpanelblockedlist.h +++ b/indra/newview/llpanelblockedlist.h @@ -36,6 +36,7 @@ class LLBlockList; class LLMenuButton; class LLButton; +#if 0 class LLPanelBlockedList : public LLPanel { public: @@ -86,6 +87,7 @@ class LLPanelBlockedList : public LLPanel LLButton* mUnblockBtn = nullptr; LLHandle<LLFloater> mPicker; }; +#endif //----------------------------------------------------------------------------- // LLFloaterGetBlockedObjectName() diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 597b44755b1..eebf8d9ae2b 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -88,7 +88,7 @@ static const std::string NEARBY_TAB_NAME = "nearby_panel"; static const std::string FRIENDS_TAB_NAME = "friends_panel"; static const std::string GROUP_TAB_NAME = "groups_panel"; static const std::string RECENT_TAB_NAME = "recent_panel"; -static const std::string BLOCKED_TAB_NAME = "blocked_panel"; // blocked avatars +//static const std::string BLOCKED_TAB_NAME = "blocked_panel"; // blocked avatars static const std::string COLLAPSED_BY_USER = "collapsed_by_user"; /** Comparator for comparing avatar items by last interaction date */ @@ -982,8 +982,8 @@ LLUUID LLPanelPeople::getCurrentItemID() const if (cur_tab == GROUP_TAB_NAME) return mGroupList->getSelectedUUID(); - if (cur_tab == BLOCKED_TAB_NAME) - return LLUUID::null; // FIXME? + //if (cur_tab == BLOCKED_TAB_NAME) + // return LLUUID::null; // FIXME? llassert(0 && "unknown tab selected"); return LLUUID::null; @@ -1005,8 +1005,8 @@ void LLPanelPeople::getCurrentItemIDs(uuid_vec_t& selected_uuids) const mRecentList->getSelectedUUIDs(selected_uuids); else if (cur_tab == GROUP_TAB_NAME) mGroupList->getSelectedUUIDs(selected_uuids); - else if (cur_tab == BLOCKED_TAB_NAME) - selected_uuids.clear(); // FIXME? + //else if (cur_tab == BLOCKED_TAB_NAME) + // selected_uuids.clear(); // FIXME? else llassert(0 && "unknown tab selected"); @@ -1582,14 +1582,14 @@ void LLPanelPeople::onOpen(const LLSD& key) if (!tab_name.empty()) { mTabContainer->selectTabByName(tab_name); - if(tab_name == BLOCKED_TAB_NAME) - { - LLPanel* blocked_tab = mTabContainer->getCurrentPanel()->findChild<LLPanel>("panel_block_list_sidetray"); - if(blocked_tab) - { - blocked_tab->onOpen(key); - } - } + //if(tab_name == BLOCKED_TAB_NAME) + //{ + // LLPanel* blocked_tab = mTabContainer->getCurrentPanel()->findChild<LLPanel>("panel_block_list_sidetray"); + // if(blocked_tab) + // { + // blocked_tab->onOpen(key); + // } + //} } } diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 44dce1ad568..e3f9be6cd97 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -69,7 +69,7 @@ #include "lllogchat.h" #include "llmutelist.h" #include "llnotificationsutil.h" -#include "llpanelblockedlist.h" +//#include "llpanelblockedlist.h" #include "llpanelprofileclassifieds.h" #include "llpanelprofilepicks.h" #include "llthumbnailctrl.h" diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 9e95f57b309..9957a3d8b9b 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1664,6 +1664,11 @@ void LLSelectMgr::dump() { LLViewerObject* objectp = (*iter)->getObject(); LL_INFOS() << "Object " << count << " type " << LLPrimitive::pCodeToString(objectp->getPCode()) << LL_ENDL; +// [SL:KB] - Patch: World-Derender | Checked: 2014-08-10 (Catznip-3.7) + LL_INFOS() << " isRoot " << objectp->isRoot() << LL_ENDL; + LL_INFOS() << " idLocal " << objectp->getLocalID() << LL_ENDL; + LL_INFOS() << " idGlobal " << objectp->getID() << LL_ENDL; +// [/SL:KB] LL_INFOS() << " hasLSL " << objectp->flagScripted() << LL_ENDL; LL_INFOS() << " hasTouch " << objectp->flagHandleTouch() << LL_ENDL; LL_INFOS() << " hasMoney " << objectp->flagTakesMoney() << LL_ENDL; @@ -6656,7 +6661,7 @@ S32 LLSelectNode::getLastSelectedTE() const return mLastTESelected; } -LLViewerObject* LLSelectNode::getObject() +LLViewerObject* LLSelectNode::getObject() const { if (!mObject) { @@ -6664,7 +6669,7 @@ LLViewerObject* LLSelectNode::getObject() } else if (mObject->isDead()) { - mObject = NULL; + mObject = nullptr; } return mObject; } diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 4205497109e..518d5453637 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -182,7 +182,7 @@ class LLSelectNode void renderOneSilhouette(const LLColor4 &color); void setTransient(BOOL transient) { mTransient = transient; } BOOL isTransient() const { return mTransient; } - LLViewerObject* getObject(); + LLViewerObject* getObject() const; void setObject(LLViewerObject* object); // *NOTE: invalidate stored textures and colors when # faces change // Used by tools floater's color/texture pickers to restore changes @@ -241,7 +241,7 @@ class LLSelectNode BOOL mSilhouetteExists; // need to generate silhouette? protected: - LLPointer<LLViewerObject> mObject; + mutable LLPointer<LLViewerObject> mObject; S32 mTESelectMask; S32 mLastTESelected; }; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index f0c2cc103a6..c820fed71c6 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -55,6 +55,9 @@ #include "llfloaterbanduration.h" #include "llfloaterbigpreview.h" #include "llfloaterbeacons.h" +// [SL:KB] - Patch: World-Derender | Checked: Catznip-3.2 +#include "llfloaterblocked.h" +// [/SL:KB] #include "llfloaterbuildoptions.h" #include "llfloaterbulkpermission.h" #include "llfloaterbump.h" @@ -351,6 +354,9 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("ban_duration", "floater_ban_duration.xml", &LLFloaterReg::build<LLFloaterBanDuration>); LLFloaterReg::add("beacons", "floater_beacons.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBeacons>); +// [SL:KB] - Patch: World-Derender | Checked: Catznip-3.2 + LLFloaterReg::add("blocked", "floater_blocked.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBlocked>); +// [/SL:KB] LLFloaterReg::add("bulk_perms", "floater_bulk_perms.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBulkPermission>); LLFloaterReg::add("buy_currency", "floater_buy_currency.xml", &LLFloaterBuyCurrency::buildFloater); LLFloaterReg::add("buy_currency_html", "floater_buy_currency_html.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuyCurrencyHTML>); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9e116a855e4..7a99fe79f3b 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -59,6 +59,9 @@ #include "llcompilequeue.h" #include "llconsole.h" #include "lldebugview.h" +// [SL:KB] - Patch: World-Derender | Checked: 2011-12-15 (Catznip-3.2) +#include "llderenderlist.h" +// [/SL:KB] #include "lldiskcache.h" #include "llenvironment.h" #include "llfilepicker.h" @@ -95,7 +98,11 @@ #include "llinventorydefines.h" #include "llinventoryfunctions.h" #include "llpanellogin.h" -#include "llpanelblockedlist.h" +// [SL:KB] - World-Mute | Checked: 2013-07-10 (Catznip-3.5) +#include "llfloaterblocked.h" +// [/SL:KB] +//#include "llpanelblockedlist.h" +#include "llfloaterblocked.h" #include "llpanelmaininventory.h" #include "llmarketplacefunctions.h" #include "llmaterialeditor.h" @@ -3539,7 +3546,8 @@ class LLObjectMute : public view_listener_t else { LLMuteList::getInstance()->add(mute); - LLPanelBlockedList::showPanelAndSelect(mute.mID); + LLFloaterBlocked::showMuteAndSelect(mute.mID); + //LLPanelBlockedList::showPanelAndSelect(mute.mID); } return true; @@ -6031,6 +6039,42 @@ void handle_force_delete(void*) LLSelectMgr::getInstance()->selectForceDelete(); } +// [SL:KB] - Patch: World-Derender | Checked: 2012-06-08 (Catznip-3.3) +void handle_view_blocked(const LLSD& sdParam) +{ + if (LLVOAvatar* pAvatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())) + { + std::string strParam = sdParam.asString(); + if (BLOCKED_TAB_NAME == strParam) + strParam = BLOCKED_PARAM_NAME; + else if (DERENDER_TAB_NAME == strParam) + strParam = DERENDER_PARAM_NAME; + else if (EXCEPTION_TAB_NAME == strParam) + strParam = EXCEPTION_PARAM_NAME; + + LLFloaterReg::showInstance("blocked", LLSD().with(strParam, pAvatar->getID())); + } + else + { + LLFloaterReg::showInstance("blocked", sdParam); + } +} + +void handle_object_derender(const LLSD& sdParam) +{ + std::vector<LLUUID> idList; + if (LLDerenderList::instance().addSelection("persistent" == sdParam.asString(), &idList)) + { + LLFloaterReg::showInstance("blocked", LLSD().with("derender_to_select", idList.front())); + } +} + +bool enable_object_derender() +{ + return LLDerenderList::canAddSelection(); +} +// [/SL:KB] + class LLViewEnableJoystickFlycam : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -7133,7 +7177,8 @@ class LLMuteParticle : public view_listener_t else { LLMuteList::getInstance()->add(mute); - LLPanelBlockedList::showPanelAndSelect(mute.mID); + LLFloaterBlocked::showMuteAndSelect(mute.mID); + //LLPanelBlockedList::showPanelAndSelect(mute.mID); } } @@ -9746,6 +9791,9 @@ void initialize_menus() view_listener_t::addMenu(new LLViewStatusAway(), "View.Status.CheckAway"); view_listener_t::addMenu(new LLViewStatusDoNotDisturb(), "View.Status.CheckDoNotDisturb"); view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments"); +// [SL:KB] - Patch: World-RenderExceptions | Checked: Catznip-5.2 + commit.add("View.Blocked", boost::bind(&handle_view_blocked, _2)); +// [/SL:KB] //Communicate Nearby chat view_listener_t::addMenu(new LLCommunicateNearbyChat(), "Communicate.NearbyChat"); @@ -10077,6 +10125,10 @@ void initialize_menus() commit.add("Object.ShowOriginal", boost::bind(&handle_object_show_original)); commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand)); commit.add("Object.Delete", boost::bind(&handle_object_delete)); +// [SL:KB] - Patch: World-Derender | Checked: 2011-12-15 (Catznip-3.2) + commit.add("Object.Derender", boost::bind(&handle_object_derender, _2)); + enable.add("Object.EnableDerender", boost::bind(&enable_object_derender)); +// [/SL:KB] view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar"); view_listener_t::addMenu(new LLObjectAttachToAvatar(false), "Object.AttachAddToAvatar"); view_listener_t::addMenu(new LLObjectReturn(), "Object.Return"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 7d03d0d1615..04eb687eb92 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -117,7 +117,8 @@ #include "llkeythrottle.h" #include "llgroupactions.h" #include "llagentui.h" -#include "llpanelblockedlist.h" +//#include "llpanelblockedlist.h" +#include "llfloaterblocked.h" #include "llpanelplaceprofile.h" #include "llviewerregion.h" #include "llfloaterregionrestarting.h" @@ -1640,7 +1641,8 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, LLMute mute(blocked_id, full_name, mute_type); if (LLMuteList::getInstance()->add(mute)) { - LLPanelBlockedList::showPanelAndSelect(blocked_id); + LLFloaterBlocked::showMuteAndSelect(blocked_id); + //LLPanelBlockedList::showPanelAndSelect(blocked_id); } // purge the message queue of any previously queued inventory offers from the same source. @@ -7068,7 +7070,8 @@ bool callback_script_dialog(const LLSD& notification, const LLSD& response) { // This call opens the sidebar, displays the block list, and highlights the newly blocked // object in the list so the user can see that their block click has taken effect. - LLPanelBlockedList::showPanelAndSelect(object_id); + //LLPanelBlockedList::showPanelAndSelect(object_id); + LLFloaterBlocked::showMuteAndSelect(object_id); } } diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index cdde4d86c67..71bc966243e 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -69,6 +69,9 @@ #include "llviewertexturelist.h" #include "lldatapacker.h" #include "llcallstack.h" +// [SL:KB] - Patch: World-Derender | Checked: 2011-12-15 (Catznip-3.2.1) +#include "llderenderlist.h" +// [/SL:KB] #ifdef LL_USESYSTEMLIBS #include <zlib.h> #else @@ -358,6 +361,15 @@ LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* } } +// [SL:KB] - Patch: World-Derender | Checked: 2014-08-10 (Catznip-3.7) + // Don't recreate derendered objects (also kill the cache entry so we don't do this per-frame) + if (LLDerenderList::instance().processObjectUpdate(regionp->getHandle(), fullid, entry)) + { + regionp->killCacheEntry(local_id); // NOTE: this will kill all child entries from the cache as well + return NULL; + } +// [/SL:KB] + bool justCreated = false; if (!objectp) { @@ -646,6 +658,27 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, } #endif +// [SL:KB] - Patch: World-Derender | Checked: 2012-06-08 (Catznip-3.3) + // Don't recreate derendered objects (update the core object information so we'll have enough information to rerequest it later if needed) + if ( (OUT_FULL == update_type) || (OUT_FULL_COMPRESSED == update_type) ) + { + bool fBlockObject = false; + if (OUT_FULL == update_type) + { + U32 idRootLocal = 0; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ParentID, idRootLocal, i); + fBlockObject = LLDerenderList::instance().processObjectUpdate(regionp->getHandle(), fullid, local_id, idRootLocal); + } + else if (OUT_FULL_COMPRESSED == update_type) + { + fBlockObject = LLDerenderList::instance().processObjectUpdate(regionp->getHandle(), fullid, local_id, compressed_dp.getBuffer()); + } + + if (fBlockObject) + continue; + } +// [/SL:KB] + objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender()); #ifdef SHOW_DEBUG diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e14f78fd00e..88b207f920d 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2837,6 +2837,10 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerB if (entry) { +// [SL:KB] - Patch: World-Derender | Checked: 2014-08-10 (Catznip-3.7) + // If the entry isn't currently valid then we shouldn't just assume everything's in perfect working order + bool fUpdateObj = (!entry->isValid()) || (entry->getCRC() != crc); +// [/SL:KB] entry->setValid(); // we've seen this object before @@ -2861,10 +2865,15 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerB // Update the cache entry entry->updateEntry(crc, dp); - decodeBoundingInfo(entry); +// decodeBoundingInfo(entry); result = CACHE_UPDATE_CHANGED; } + +// [SL:KB] - Patch: World-Derender | Checked: 2014-08-10 (Catznip-3.7) + if (fUpdateObj) + decodeBoundingInfo(entry); +// [/SL:KB] } else { diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index e1fd2b206ce..4c111d655af 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -413,7 +413,7 @@ LLVOCacheEntry* LLVOCacheEntry::getChild() return child; } -LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP() +LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP() const { if (mDP.getBufferSize() == 0) { diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index c0f4b3ae6a5..1eac9253d3f 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -130,7 +130,7 @@ class LLVOCacheEntry final void dump() const; S32 writeToBuffer(U8 *data_buffer) const; - LLDataPackerBinaryBuffer *getDP(); + LLDataPackerBinaryBuffer *getDP() const; void recordHit(); void recordDupe() { mDupeCount++; } @@ -169,6 +169,11 @@ class LLVOCacheEntry final typedef std::unordered_map<U32, LLGLTFOverrideCacheEntry> vocache_gltf_overrides_map_t; +// [SL:KB] - Patch: World-Derender | Checked: 2014-08-10 (Catznip-3.7) + vocache_entry_set_t::const_iterator getChildrenBegin() const { return mChildrenList.begin(); } + vocache_entry_set_t::const_iterator getChildrenEnd() const { return mChildrenList.end(); } +// [/SL:KB] + S32 mLastCameraUpdated; protected: U32 mLocalID; @@ -178,7 +183,7 @@ class LLVOCacheEntry final S32 mHitCount; S32 mDupeCount; S32 mCRCChangeCount; - LLDataPackerBinaryBuffer mDP; + mutable LLDataPackerBinaryBuffer mDP; U8 *mBuffer; F32 mSceneContrib; //projected scene contributuion of this object. diff --git a/indra/newview/skins/default/xui/en/floater_blocked.xml b/indra/newview/skins/default/xui/en/floater_blocked.xml new file mode 100644 index 00000000000..5033927fde7 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_blocked.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_close="true" + can_minimize="true" + can_resize="true" + height="300" + help_topic="blocked_list" + layout="topleft" + min_height="300" + min_width="330" + name="blocked" + positioning="cascading" + save_rect="true" + save_visibility="false" + single_instance="true" + title="BLOCKED / DERENDER LIST" + width="350"> + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="15" + label="Filter" + max_length_chars="300" + name="blocked_filter" + right="-15" + text_pad_left="10" + top="4" + /> + <tab_container + follows="all" + layout="topleft" + left="8" + name="blocked_tabs" + height="267" + right="-8" + tab_height="25" + tab_min_width="100" + tab_position="top" + top_pad="4" > + <panel + class="panel_block_list" + filename="panel_block_list.xml" + label="BLOCKED" + layout="topleft" + name="mute_tab" /> + <panel + class="panel_derender_list" + filename="panel_block_derender.xml" + label="DERENDERED" + layout="topleft" + name="derender_tab" /> + <panel + class="panel_block_avatar_rendering" + filename="panel_block_avatar_rendering.xml" + label="AVATAR RENDERING" + layout="topleft" + name="avatar_rendering_tab" /> + </tab_container> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml index 2662b0df702..6afa27c3f33 100644 --- a/indra/newview/skins/default/xui/en/menu_attachment_other.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml @@ -105,8 +105,8 @@ label="Render Exceptions..." name="RenderExceptions"> <menu_item_call.on_click - function="Floater.ToggleOrBringToFront" - parameter="avatar_render_settings" /> + function="View.Blocked" + parameter="avatar_rendering_tab" /> </menu_item_call> </context_menu> <context_menu diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml index 26819704b69..8145b465c1d 100644 --- a/indra/newview/skins/default/xui/en/menu_avatar_other.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml @@ -107,8 +107,8 @@ label="Render Exceptions..." name="RenderExceptions"> <menu_item_call.on_click - function="Floater.ToggleOrBringToFront" - parameter="avatar_render_settings" /> + function="View.Blocked" + parameter="avatar_rendering_tab" /> </menu_item_call> </context_menu> <context_menu diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml index 58accf7429f..51d68c22732 100644 --- a/indra/newview/skins/default/xui/en/menu_object.xml +++ b/indra/newview/skins/default/xui/en/menu_object.xml @@ -251,6 +251,7 @@ <menu_item_call.on_enable function="Object.EnableReportAbuse" /> </menu_item_call> + <menu_item_separator /> <menu_item_call label="Block" name="Object Mute"> @@ -267,6 +268,25 @@ <menu_item_call.on_visible function="Object.EnableUnmute" /> </menu_item_call> + <menu_item_call + label="Session Derender" + name="Object Session Derender"> + <menu_item_call.on_click + function="Object.Derender" + parameter="temporary" /> + <menu_item_call.on_enable + function="Object.EnableDerender" /> + </menu_item_call> + <menu_item_call + label="Permanent Derender" + name="Object Permanent Derender"> + <menu_item_call.on_click + function="Object.Derender" + parameter="persistent" /> + <menu_item_call.on_enable + function="Object.EnableDerender" /> + </menu_item_call> + <menu_item_separator /> <menu_item_call enabled="false" label="Return" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index e0b7cae5398..a954e1c4ab3 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -671,11 +671,11 @@ label="Block List" name="Block List"> <menu_item_check.on_check - function="SideTray.CheckPanelPeopleTab" - parameter="blocked_panel" /> + function="Floater.Visible" + parameter="blocked" /> <menu_item_check.on_click - function="SideTray.PanelPeopleTab" - parameter="blocked_panel" /> + function="Floater.Toggle" + parameter="blocked" /> </menu_item_check> <menu_item_separator/> <menu_item_check diff --git a/indra/newview/skins/default/xui/en/panel_block_avatar_rendering.xml b/indra/newview/skins/default/xui/en/panel_block_avatar_rendering.xml new file mode 100644 index 00000000000..e43bf81032a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_block_avatar_rendering.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<panel + follows="all" + height="300" + label="AVATAR RENDERING" + layout="topleft" + name="panel_block_avatar_rendering" + width="350"> + <string + name="av_never_render" + value="Never"/> + <string + name="av_always_render" + value="Always"/> + <name_list + draw_heading="true" + follows="all" + height="275" + layout="topleft" + left="1" + multi_select="false" + name="exception_list" + right="-1" + top="0" > + <name_list.columns + label="Name" + name="name" + relative_width="0.5" /> + <name_list.columns + label="Render setting" + name="setting" + relative_width="0.25" /> + <name_list.columns + label="Date added" + name="timestamp" + relative_width="0.25" /> + </name_list> + <panel + follows="left|right|bottom" + height="25" + left="1" + layout="topleft" + name="bottom_panel" + right="-1" + top_pad="0" > + <button + follows="left|bottom" + height="25" + image_hover_unselected="Toolbar_Left_Over" + image_overlay="AddItem_Off" + image_overlay_alignment="left" + image_selected="Toolbar_Left_Selected" + image_unselected="Toolbar_Left_Off" + label="Always Render" + left="1" + name="rendering_exception_always_btn" + tool_tip="Pick a resident to always render" + top="0" + width="119"> + <button.commit_callback + function="Rendering.AddException" + parameter="always" /> + </button> + <button + follows="left|bottom" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_overlay_alignment="left" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + label="Never Render" + left_pad="1" + name="rendering_exception_never_btn" + tool_tip="Pick a resident to never render" + width="109"> + <button.commit_callback + function="Rendering.AddException" + parameter="never" /> + </button> + <icon + follows="left|bottom|right" + height="25" + image_name="Toolbar_Middle_Off" + left_pad="1" + right="-80" + name="rendering_spacer_icon" /> + <button + enabled="false" + follows="bottom|right" + height="25" + image_hover_unselected="Toolbar_Right_Over" + image_overlay="TrashItem_Off" + image_overlay_alignment="left" + image_selected="Toolbar_Right_Selected" + image_unselected="Toolbar_Right_Off" + label="Remove" + left_pad="1" + name="rendering_exception_trash_btn" + tool_tip="Remove the currently selected rendering exception" + width="79"> + <button.commit_callback + function="Rendering.RemoveException" /> + </button> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_block_derender.xml b/indra/newview/skins/default/xui/en/panel_block_derender.xml new file mode 100644 index 00000000000..b5e1c2331ec --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_block_derender.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="all" + height="300" + label="DERENDERED LIST" + layout="topleft" + width="350"> + <scroll_list + draw_border="false" + draw_heading="true" + draw_stripes="true" + follows="all" + height="275" + layout="topleft" + left="1" + multi_select="true" + name="derender_list" + right="-1" + tool_tip="List of currently derendered objects." + top="0" > + <scroll_list.columns + label="Object Name" + name="object_name" /> + <scroll_list.columns + label="Location" + name="location" + width="140" /> + <scroll_list.columns + label="Type" + name="derender_type" + width="80" /> + </scroll_list> + <panel + follows="left|right|bottom" + height="25" + left="1" + layout="topleft" + name="bottom_panel" + right="-1" + top_pad="0" > + <icon + follows="bottom|left|right" + height="25" + image_name="Toolbar_Left_Off" + width="472" + left="1" + name="derender_spacer_icon" + right="-80" + top="0" /> + <button + enabled="false" + follows="bottom|right" + height="25" + image_hover_unselected="Toolbar_Right_Over" + image_overlay="TrashItem_Off" + image_overlay_alignment="left" + image_selected="Toolbar_Right_Selected" + image_unselected="Toolbar_Right_Off" + label="Restore" + left_pad="1" + name="derender_trash_btn" + tool_tip="Restore selected objects." + width="79" /> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_block_list.xml b/indra/newview/skins/default/xui/en/panel_block_list.xml new file mode 100644 index 00000000000..5594d7e57dc --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_block_list.xml @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="all" + height="300" + label="BLOCKED LIST" + layout="topleft" + name="panel_block_list" + width="350"> + <scroll_list + draw_border="false" + draw_heading="true" + draw_stripes="true" + follows="all" + height="275" + layout="topleft" + left="1" + multi_select="true" + name="block_list" + right="-1" + tool_tip="List of currently blocked Residents / Objects." + top="0" > + <scroll_list.columns + label="Name" + name="item_name" /> + <scroll_list.columns + label="Block Type" + name="item_type" + width="100" /> + <scroll_list.columns + can_sort="false" + halign="center" + label="T" + name="item_text" + tool_tip="Text" + width="20" /> + <scroll_list.columns + can_sort="false" + halign="center" + label="V" + name="item_voice" + tool_tip="Voice" + width="20" /> + <scroll_list.columns + can_sort="false" + halign="center" + label="P" + name="item_particles" + tool_tip="Particles" + width="20" /> + <scroll_list.columns + can_sort="false" + halign="center" + label="S" + name="item_sounds" + tool_tip="Object Sounds" + width="20" /> + </scroll_list> + <panel + follows="left|right|bottom" + height="25" + left="1" + layout="topleft" + name="bottom_panel" + right="-1" + top_pad="0" > + <button + follows="left|bottom" + height="25" + image_hover_unselected="Toolbar_Left_Over" + image_overlay="AddItem_Off" + image_overlay_alignment="left" + image_selected="Toolbar_Left_Selected" + image_unselected="Toolbar_Left_Off" + label="Block Resident" + left="1" + name="block_resident_btn" + tool_tip="Pick a resident to block" + top="0" + width="119"> + <button.commit_callback + function="Block.AddAvatar" /> + </button> + <button + follows="left|bottom" + height="25" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_overlay_alignment="left" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + label="Block Object" + left_pad="1" + name="block_object_btn" + tool_tip="Pick an object to block by name" + width="109"> + <button.commit_callback + function="Block.AddByName" /> + </button> + <icon + follows="left|bottom|right" + height="25" + image_name="Toolbar_Middle_Off" + left_pad="1" + right="-80" + name="derenderx_spacer_icon" /> + <button + enabled="false" + follows="bottom|right" + height="25" + image_hover_unselected="Toolbar_Right_Over" + image_overlay="TrashItem_Off" + image_overlay_alignment="left" + image_selected="Toolbar_Right_Selected" + image_unselected="Toolbar_Right_Off" + label="Unblock" + left_pad="1" + name="block_trash_btn" + tool_tip="Remove selected items from the blocked list" + width="79"> + <button.commit_callback + function="Block.Remove" /> + </button> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 97b7964e8b9..a3451c92a5c 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -631,7 +631,7 @@ Learn about [https://community.secondlife.com/knowledgebase/joining-and-particip <!-- ================================= BLOCKED tab ========================== --> - <panel + <!--<panel background_opaque="true" background_visible="true" bg_alpha_color="DkGray" @@ -657,6 +657,6 @@ Learn about [https://community.secondlife.com/knowledgebase/joining-and-particip font="SansSerifBold" top="0" right="-1" /> - </panel> + </panel>--> </tab_container> </panel> -- GitLab