summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
authorAndrey Lihatskiy <alihatskiy@productengine.com>2021-07-23 07:10:26 +0300
committerAndrey Lihatskiy <alihatskiy@productengine.com>2021-07-23 07:10:26 +0300
commit638fe8757694b4039e8b88d83fb8b7b7cfafb1a4 (patch)
tree2c4fb2a4d4db5022c395bafde44e01666d08a868 /indra/llui
parent7587f0dd88526e61a4741ad8e2d9894027de1ffb (diff)
parentbe6066eae218856f7fd74b98968a75e5062fa830 (diff)
Merge branch 'master' into DRTVWR-483
# Conflicts: # indra/newview/llpanelpicks.cpp # indra/newview/llpanelpicks.h # indra/newview/llviewerfloaterreg.cpp
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/CMakeLists.txt2
-rw-r--r--indra/llui/llaccordionctrltab.cpp2
-rw-r--r--indra/llui/llbutton.cpp8
-rw-r--r--indra/llui/llchat.h6
-rw-r--r--indra/llui/llconsole.cpp4
-rw-r--r--indra/llui/llfloater.cpp33
-rw-r--r--indra/llui/llfloater.h6
-rw-r--r--indra/llui/llfloaterreg.cpp8
-rw-r--r--indra/llui/llfloaterreg.h1
-rw-r--r--indra/llui/llfolderview.cpp9
-rw-r--r--indra/llui/llfolderviewitem.cpp13
-rw-r--r--indra/llui/llfolderviewitem.h2
-rw-r--r--indra/llui/llfolderviewmodel.cpp6
-rw-r--r--indra/llui/lllineeditor.h3
-rw-r--r--indra/llui/llmenugl.cpp4
-rw-r--r--indra/llui/llmultislider.cpp23
-rw-r--r--indra/llui/llmultislider.h1
-rw-r--r--indra/llui/llnotificationptr.h3
-rw-r--r--indra/llui/llnotifications.cpp1
-rw-r--r--indra/llui/llnotifications.h16
-rw-r--r--indra/llui/llscrolllistcolumn.cpp4
-rw-r--r--indra/llui/llscrolllistctrl.cpp4
-rw-r--r--indra/llui/llsearcheditor.cpp22
-rw-r--r--indra/llui/llsearcheditor.h20
-rw-r--r--indra/llui/lltabcontainer.cpp3
-rw-r--r--indra/llui/lltoolbar.cpp6
-rw-r--r--indra/llui/lltooltip.cpp4
-rw-r--r--indra/llui/llui.cpp26
-rw-r--r--indra/llui/llui.h20
-rw-r--r--indra/llui/lluictrl.cpp22
-rw-r--r--indra/llui/lluictrl.h4
-rw-r--r--indra/llui/lluiusage.cpp146
-rw-r--r--indra/llui/lluiusage.h57
-rw-r--r--indra/llui/llurlentry.cpp8
-rw-r--r--indra/llui/llview.cpp22
-rw-r--r--indra/llui/llview.h3
-rw-r--r--indra/llui/llvirtualtrackball.cpp40
-rw-r--r--indra/llui/llvirtualtrackball.h3
-rw-r--r--indra/llui/tests/llurlentry_test.cpp5
39 files changed, 479 insertions, 91 deletions
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index cce618487b..f781ff4110 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -122,6 +122,7 @@ set(llui_SOURCE_FILES
lluictrl.cpp
lluictrlfactory.cpp
lluistring.cpp
+ lluiusage.cpp
llundo.cpp
llurlaction.cpp
llurlentry.cpp
@@ -241,6 +242,7 @@ set(llui_HEADER_FILES
llui.h
lluicolor.h
lluistring.h
+ lluiusage.h
llundo.h
llurlaction.h
llurlentry.h
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 098621b543..04485c6262 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -1006,7 +1006,7 @@ void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child)
LLRect screen_rect;
localRectToScreen(child->getRect(),&screen_rect);
- if ( root_rect.overlaps(screen_rect) && LLUI::getInstance()->mDirtyRect.overlaps(screen_rect))
+ if ( root_rect.overlaps(screen_rect) && sDirtyRect.overlaps(screen_rect))
{
gGL.matrixMode(LLRender::MM_MODELVIEW);
LLUI::pushMatrix();
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 9682c3bc10..0e59fdf519 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -47,6 +47,7 @@
#include "llnotificationsutil.h"
#include "llrender.h"
#include "lluictrlfactory.h"
+#include "lluiusage.h"
#include "llhelp.h"
#include "lldockablefloater.h"
#include "llviewereventrecorder.h"
@@ -437,6 +438,13 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)
setFocus(TRUE);
}
+ if (!mFunctionName.empty())
+ {
+ LL_DEBUGS("UIUsage") << "calling mouse down function " << mFunctionName << LL_ENDL;
+ LLUIUsage::instance().logCommand(mFunctionName);
+ LLUIUsage::instance().logControl(getPathname());
+ }
+
/*
* ATTENTION! This call fires another mouse down callback.
* If you wish to remove this call emit that signal directly
diff --git a/indra/llui/llchat.h b/indra/llui/llchat.h
index f5b242fdfc..c39e44200c 100644
--- a/indra/llui/llchat.h
+++ b/indra/llui/llchat.h
@@ -37,7 +37,8 @@ typedef enum e_chat_source_type
CHAT_SOURCE_SYSTEM = 0,
CHAT_SOURCE_AGENT = 1,
CHAT_SOURCE_OBJECT = 2,
- CHAT_SOURCE_UNKNOWN = 3
+ CHAT_SOURCE_TELEPORT = 3,
+ CHAT_SOURCE_UNKNOWN = 4
} EChatSourceType;
typedef enum e_chat_type
@@ -64,7 +65,8 @@ typedef enum e_chat_style
{
CHAT_STYLE_NORMAL,
CHAT_STYLE_IRC,
- CHAT_STYLE_HISTORY
+ CHAT_STYLE_HISTORY,
+ CHAT_STYLE_TELEPORT_SEP
}EChatStyle;
// A piece of chat
diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp
index 7817d99aef..8fc2978bdd 100644
--- a/indra/llui/llconsole.cpp
+++ b/indra/llui/llconsole.cpp
@@ -180,7 +180,9 @@ void LLConsole::draw()
LLUIImagePtr imagep = LLUI::getUIImage("transparent");
- F32 console_opacity = llclamp(LLUI::getInstance()->mSettingGroups["config"]->getF32("ConsoleBackgroundOpacity"), 0.f, 1.f);
+ static LLCachedControl<F32> console_bg_opacity(*LLUI::getInstance()->mSettingGroups["config"], "ConsoleBackgroundOpacity", 0.7f);
+ F32 console_opacity = llclamp(console_bg_opacity(), 0.f, 1.f);
+
LLColor4 color = LLUIColorTable::instance().getColor("ConsoleBackground");
color.mV[VALPHA] *= console_opacity;
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 61f2767b5c..f20c859ac4 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -58,6 +58,7 @@
#include "llhelp.h"
#include "llmultifloater.h"
#include "llsdutil.h"
+#include "lluiusage.h"
#include <boost/foreach.hpp>
@@ -198,7 +199,9 @@ LLFloater::Params::Params()
help_pressed_image("help_pressed_image"),
open_callback("open_callback"),
close_callback("close_callback"),
- follows("follows")
+ follows("follows"),
+ rel_x("rel_x", 0),
+ rel_y("rel_y", 0)
{
changeDefault(visible, false);
}
@@ -268,6 +271,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
mHasBeenDraggedWhileMinimized(FALSE),
mPreviousMinimizedBottom(0),
mPreviousMinimizedLeft(0),
+ mDefaultRelativeX(p.rel_x),
+ mDefaultRelativeY(p.rel_y),
mMinimizeSignal(NULL)
// mNotificationContext(NULL)
{
@@ -377,13 +382,15 @@ void LLFloater::layoutDragHandle()
// static
void LLFloater::updateActiveFloaterTransparency()
{
- sActiveControlTransparency = LLUI::getInstance()->mSettingGroups["config"]->getF32("ActiveFloaterTransparency");
+ static LLCachedControl<F32> active_transparency(*LLUI::getInstance()->mSettingGroups["config"], "ActiveFloaterTransparency", 1.f);
+ sActiveControlTransparency = active_transparency;
}
// static
void LLFloater::updateInactiveFloaterTransparency()
{
- sInactiveControlTransparency = LLUI::getInstance()->mSettingGroups["config"]->getF32("InactiveFloaterTransparency");
+ static LLCachedControl<F32> inactive_transparency(*LLUI::getInstance()->mSettingGroups["config"], "InactiveFloaterTransparency", 0.95f);
+ sInactiveControlTransparency = inactive_transparency;
}
void LLFloater::addResizeCtrls()
@@ -506,7 +513,12 @@ void LLFloater::destroy()
// virtual
LLFloater::~LLFloater()
{
- LLFloaterReg::removeInstance(mInstanceName, mKey);
+ if (!isDead())
+ {
+ // If it's dead, instance is supposed to be already removed, and
+ // in case of single instance we can remove new one by accident
+ LLFloaterReg::removeInstance(mInstanceName, mKey);
+ }
if( gFocusMgr.childHasKeyboardFocus(this))
{
@@ -938,6 +950,15 @@ bool LLFloater::applyRectControl()
saved_rect = true;
}
+ else if ((mDefaultRelativeX != 0) && (mDefaultRelativeY != 0))
+ {
+ mPosition.mX = mDefaultRelativeX;
+ mPosition.mY = mDefaultRelativeY;
+ mPositioning = LLFloaterEnums::POSITIONING_RELATIVE;
+ applyRelativePosition();
+
+ saved_rect = true;
+ }
// remember updated position
if (rect_specified)
@@ -1635,6 +1656,7 @@ void LLFloater::bringToFront( S32 x, S32 y )
// virtual
void LLFloater::setVisibleAndFrontmost(BOOL take_focus,const LLSD& key)
{
+ LLUIUsage::instance().logFloater(getInstanceName());
LLMultiFloater* hostp = getHost();
if (hostp)
{
@@ -3202,6 +3224,9 @@ void LLFloater::initFromParams(const LLFloater::Params& p)
mSingleInstance = p.single_instance;
mReuseInstance = p.reuse_instance.isProvided() ? p.reuse_instance : p.single_instance;
+ mDefaultRelativeX = p.rel_x;
+ mDefaultRelativeY = p.rel_y;
+
mPositioning = p.positioning;
mSaveRect = p.save_rect;
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 8dffe3c255..db0bbfef30 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -172,6 +172,9 @@ public:
Optional<S32> header_height,
legacy_header_height; // HACK see initFromXML()
+ Optional<F32> rel_x,
+ rel_y;
+
// Images for top-right controls
Optional<LLUIImage*> close_image,
restore_image,
@@ -522,6 +525,9 @@ private:
BOOL mHasBeenDraggedWhileMinimized;
S32 mPreviousMinimizedBottom;
S32 mPreviousMinimizedLeft;
+
+ F32 mDefaultRelativeX;
+ F32 mDefaultRelativeY;
};
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index 85e07fc6a6..36a0cb0fd0 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -32,6 +32,7 @@
#include "llfloater.h"
#include "llmultifloater.h"
#include "llfloaterreglistener.h"
+#include "lluiusage.h"
//*******************************************************
@@ -57,6 +58,12 @@ void LLFloaterReg::add(const std::string& name, const std::string& filename, con
}
//static
+bool LLFloaterReg::isRegistered(const std::string& name)
+{
+ return sBuildMap.find(name) != sBuildMap.end();
+}
+
+//static
LLFloater* LLFloaterReg::getLastFloaterInGroup(const std::string& name)
{
const std::string& groupname = sGroupMap[name];
@@ -472,7 +479,6 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
std::string name = sdname.asString();
LLFloater* instance = getInstance(name, key);
-
if (!instance)
{
LL_DEBUGS() << "Unable to get instance of floater '" << name << "'" << LL_ENDL;
diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h
index e3b17dcb4f..a457a15673 100644
--- a/indra/llui/llfloaterreg.h
+++ b/indra/llui/llfloaterreg.h
@@ -85,6 +85,7 @@ public:
static void add(const std::string& name, const std::string& file, const LLFloaterBuildFunc& func,
const std::string& groupname = LLStringUtil::null);
+ static bool isRegistered(const std::string& name);
// Helpers
static LLFloater* getLastFloaterInGroup(const std::string& name);
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 0c1dcc301b..622c9edba7 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -342,9 +342,9 @@ static LLTrace::BlockTimerStatHandle FTM_FILTER("Filter Folder View");
void LLFolderView::filter( LLFolderViewFilter& filter )
{
LL_RECORD_BLOCK_TIME(FTM_FILTER);
- static LLCachedControl<S32> filter_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
- static LLCachedControl<S32> filter_hidden(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1);
- filter.resetTime(llclamp(mParentPanel.get()->getVisible() ? filter_visible() : filter_hidden(), 1, 100));
+ static LLCachedControl<S32> time_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
+ static LLCachedControl<S32> time_invisible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1);
+ filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? time_visible() : time_invisible()), 1, 100));
// Note: we filter the model, not the view
getViewModelItem()->filter(filter);
@@ -663,7 +663,8 @@ void LLFolderView::draw()
closeAutoOpenedFolders();
}
- if (mSearchTimer.getElapsedTimeF32() > LLUI::getInstance()->mSettingGroups["config"]->getF32("TypeAheadTimeout") || !mSearchString.size())
+ static LLCachedControl<F32> type_ahead_timeout(*LLUI::getInstance()->mSettingGroups["config"], "TypeAheadTimeout", 1.5f);
+ if (mSearchTimer.getElapsedTimeF32() > type_ahead_timeout || !mSearchString.size())
{
mSearchString.clear();
}
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 1c6c7b1b35..285bf9f484 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -962,9 +962,10 @@ void LLFolderViewItem::draw()
//
if (filter_string_length > 0)
{
- F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mViewModelItem->getFilterStringOffset());
+ S32 filter_offset = mViewModelItem->getFilterStringOffset();
+ F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, filter_offset + filter_string_length) - font->getWidthF32(combined_string, filter_offset, filter_string_length);
F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD;
- font->renderUTF8( combined_string, mViewModelItem->getFilterStringOffset(), match_string_left, yy,
+ font->renderUTF8( combined_string, filter_offset, match_string_left, yy,
sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
filter_string_length, S32_MAX, &right_x, FALSE );
}
@@ -1607,7 +1608,7 @@ void LLFolderViewFolder::destroyView()
// extractItem() removes the specified item from the folder, but
// doesn't delete it.
-void LLFolderViewFolder::extractItem( LLFolderViewItem* item )
+void LLFolderViewFolder::extractItem( LLFolderViewItem* item, bool deparent_model )
{
if (item->isSelected())
getRoot()->clearSelection();
@@ -1630,7 +1631,11 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item )
mItems.erase(it);
}
//item has been removed, need to update filter
- getViewModelItem()->removeChild(item->getViewModelItem());
+ if (deparent_model)
+ {
+ // in some cases model does not belong to parent view, is shared between views
+ getViewModelItem()->removeChild(item->getViewModelItem());
+ }
//because an item is going away regardless of filter status, force rearrange
requestArrange();
removeChild(item);
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index da09d139e9..616d2e7d86 100644
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -387,7 +387,7 @@ public:
// extractItem() removes the specified item from the folder, but
// doesn't delete it.
- virtual void extractItem( LLFolderViewItem* item );
+ virtual void extractItem( LLFolderViewItem* item, bool deparent_model = true);
// This function is called by a child that needs to be resorted.
void resort(LLFolderViewItem* item);
diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp
index ea106b5fae..93122503d1 100644
--- a/indra/llui/llfolderviewmodel.cpp
+++ b/indra/llui/llfolderviewmodel.cpp
@@ -48,9 +48,9 @@ std::string LLFolderViewModelCommon::getStatusText()
void LLFolderViewModelCommon::filter()
{
- static LLCachedControl<S32> filter_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
- getFilter().resetTime(llclamp(filter_visible(), 1, 100));
- mFolderView->getViewModelItem()->filter(getFilter());
+ static LLCachedControl<S32> max_time(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
+ getFilter().resetTime(llclamp(max_time(), 1, 100));
+ mFolderView->getViewModelItem()->filter(getFilter());
}
bool LLFolderViewModelItemCommon::hasFilterStringMatch()
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index aa5779d45f..f84625bea7 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -283,6 +283,9 @@ public:
void resetContextMenu() { setContextMenu(NULL); };
+ void setBgImage(LLPointer<LLUIImage> image) { mBgImage = image; }
+ void setBgImageFocused(LLPointer<LLUIImage> image) { mBgImageFocused = image; }
+
private:
// private helper methods
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 37dbe9b40e..cdaf03ebde 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -79,7 +79,7 @@ const U32 LEFT_PAD_PIXELS = 3;
const U32 LEFT_WIDTH_PIXELS = 15;
const U32 LEFT_PLAIN_PIXELS = LEFT_PAD_PIXELS + LEFT_WIDTH_PIXELS;
-const U32 RIGHT_PAD_PIXELS = 2;
+const U32 RIGHT_PAD_PIXELS = 7;
const U32 RIGHT_WIDTH_PIXELS = 15;
const U32 RIGHT_PLAIN_PIXELS = RIGHT_PAD_PIXELS + RIGHT_WIDTH_PIXELS;
@@ -95,7 +95,7 @@ const std::string SEPARATOR_NAME("separator");
const std::string VERTICAL_SEPARATOR_LABEL( "|" );
const std::string LLMenuGL::BOOLEAN_TRUE_PREFIX( "\xE2\x9C\x94" ); // U+2714 HEAVY CHECK MARK
-const std::string LLMenuGL::BRANCH_SUFFIX( "\xE2\x96\xB6" ); // U+25B6 BLACK RIGHT-POINTING TRIANGLE
+const std::string LLMenuGL::BRANCH_SUFFIX( "\xe2\x96\xb8" ); // U+25B6 BLACK RIGHT-POINTING TRIANGLE
const std::string LLMenuGL::ARROW_UP ("^^^^^^^");
const std::string LLMenuGL::ARROW_DOWN("vvvvvvv");
diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp
index acfe4a0cba..f89064d59a 100644
--- a/indra/llui/llmultislider.cpp
+++ b/indra/llui/llmultislider.cpp
@@ -136,6 +136,7 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)
}
}
+ mRoundedSquareImgp = LLUI::getUIImage("Rounded_Square");
if (p.thumb_image.isProvided())
{
mThumbImagep = LLUI::getUIImage(p.thumb_image());
@@ -666,8 +667,6 @@ void LLMultiSlider::draw()
F32 opacity = getEnabled() ? 1.f : 0.3f;
// Track
- LLUIImagePtr thumb_imagep = LLUI::getUIImage("Rounded_Square");
-
static LLUICachedControl<S32> multi_track_height_width ("UIMultiTrackHeight", 0);
S32 height_offset = 0;
S32 width_offset = 0;
@@ -685,7 +684,7 @@ void LLMultiSlider::draw()
if(mDrawTrack)
{
track_rect.stretch(-1);
- thumb_imagep->draw(track_rect, mTrackColor.get() % opacity);
+ mRoundedSquareImgp->draw(track_rect, mTrackColor.get() % opacity);
}
// if we're supposed to use a drawn triangle
@@ -704,7 +703,7 @@ void LLMultiSlider::draw()
mTriangleColor.get() % opacity, TRUE);
}
}
- else if (!thumb_imagep && !mThumbImagep)
+ else if (!mRoundedSquareImgp && !mThumbImagep)
{
// draw all the thumbs
curSldrIt = mThumbRects.end();
@@ -757,7 +756,7 @@ void LLMultiSlider::draw()
}
else
{
- thumb_imagep->drawSolid(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f);
+ mRoundedSquareImgp->drawSolid(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f);
}
}
@@ -772,7 +771,7 @@ void LLMultiSlider::draw()
}
else
{
- thumb_imagep->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
+ mRoundedSquareImgp->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
}
}
}
@@ -784,7 +783,7 @@ void LLMultiSlider::draw()
}
else
{
- thumb_imagep->drawBorder(mThumbRects[mHoverSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
+ mRoundedSquareImgp->drawBorder(mThumbRects[mHoverSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
}
}
@@ -822,11 +821,11 @@ void LLMultiSlider::draw()
}
else if (capture == this)
{
- thumb_imagep->drawSolid(mIt->second, curThumbColor);
+ mRoundedSquareImgp->drawSolid(mIt->second, curThumbColor);
}
else
{
- thumb_imagep->drawSolid(mIt->second, curThumbColor % opacity);
+ mRoundedSquareImgp->drawSolid(mIt->second, curThumbColor % opacity);
}
}
@@ -846,11 +845,11 @@ void LLMultiSlider::draw()
}
else if (capture == this)
{
- thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get());
+ mRoundedSquareImgp->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get());
}
else
{
- thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get() % opacity);
+ mRoundedSquareImgp->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get() % opacity);
}
}
if(hoverSldrIt != mThumbRects.end())
@@ -861,7 +860,7 @@ void LLMultiSlider::draw()
}
else
{
- thumb_imagep->drawSolid(hoverSldrIt->second, mThumbCenterSelectedColor.get());
+ mRoundedSquareImgp->drawSolid(hoverSldrIt->second, mThumbCenterSelectedColor.get());
}
}
}
diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h
index 99a78d6e09..3cb4b760b0 100644
--- a/indra/llui/llmultislider.h
+++ b/indra/llui/llmultislider.h
@@ -150,6 +150,7 @@ protected:
LLUIColor mDisabledThumbColor;
LLUIColor mTriangleColor;
LLUIImagePtr mThumbImagep; //blimps on the slider, for now no 'disabled' support
+ LLUIImagePtr mRoundedSquareImgp; //blimps on the slider, for now no 'disabled' support
const EOrientation mOrientation;
diff --git a/indra/llui/llnotificationptr.h b/indra/llui/llnotificationptr.h
index acc047527f..580f353c7d 100644
--- a/indra/llui/llnotificationptr.h
+++ b/indra/llui/llnotificationptr.h
@@ -27,9 +27,8 @@
// Many classes just store a single LLNotificationPtr
// and llnotifications.h is very large, so define this ligher header.
-#include <boost/shared_ptr.hpp>
class LLNotification;
-typedef boost::shared_ptr<LLNotification> LLNotificationPtr;
+typedef std::shared_ptr<LLNotification> LLNotificationPtr;
#endif
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 06ec648178..b791a19c2b 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -77,6 +77,7 @@ LLNotificationForm::FormButton::FormButton()
text("text"),
ignore("ignore"),
is_default("default"),
+ width("width", 0),
type("type")
{
// set type here so it gets serialized
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 2f4578da17..b1123d27e5 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -85,7 +85,6 @@
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
-#include <boost/enable_shared_from_this.hpp>
#include <boost/type_traits.hpp>
#include <boost/signals2.hpp>
#include <boost/range.hpp>
@@ -191,6 +190,7 @@ public:
Mandatory<std::string> text;
Optional<std::string> ignore;
Optional<bool> is_default;
+ Optional<S32> width;
Mandatory<std::string> type;
@@ -304,7 +304,7 @@ typedef boost::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibility
*/
class LLNotification :
boost::noncopyable,
- public boost::enable_shared_from_this<LLNotification>
+ public std::enable_shared_from_this<LLNotification>
{
LOG_CLASS(LLNotification);
friend class LLNotifications;
@@ -743,7 +743,10 @@ public:
: mFilter(filter),
mItems()
{}
- virtual ~LLNotificationChannelBase() {}
+ virtual ~LLNotificationChannelBase()
+ {
+ mItems.clear();
+ }
// you can also connect to a Channel, so you can be notified of
// changes to this channel
LLBoundListener connectChanged(const LLEventListener& slot)
@@ -873,6 +876,7 @@ class LLNotifications :
{
LLSINGLETON(LLNotifications);
LOG_CLASS(LLNotifications);
+ virtual ~LLNotifications() {}
public:
@@ -1070,7 +1074,11 @@ public:
LLPersistentNotificationChannel()
: LLNotificationChannel("Persistent", "Visible", &notificationFilter)
{}
- virtual ~LLPersistentNotificationChannel() {}
+
+ virtual ~LLPersistentNotificationChannel()
+ {
+ mHistory.clear();
+ }
typedef std::vector<LLNotificationPtr> history_list_t;
history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); }
diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp
index cc9ff7a487..82b0415624 100644
--- a/indra/llui/llscrolllistcolumn.cpp
+++ b/indra/llui/llscrolllistcolumn.cpp
@@ -257,7 +257,7 @@ void LLScrollColumnHeader::updateResizeBars()
for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
{
LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
- if (columnp->mHeader && columnp->mHeader->canResize())
+ if (columnp && columnp->mHeader && columnp->mHeader->canResize())
{
num_resizable_columns++;
}
@@ -269,7 +269,7 @@ void LLScrollColumnHeader::updateResizeBars()
for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
{
LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
- if (!columnp->mHeader) continue;
+ if (!columnp || !columnp->mHeader) continue;
BOOL enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize();
columnp->mHeader->enableResizeBar(enable);
if (enable)
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index be85f1cb6a..de644185fd 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -743,12 +743,12 @@ void LLScrollListCtrl::updateColumns(bool force_update)
LLScrollColumnHeader* last_header = NULL;
for (column_ordered_it = mColumnsIndexed.begin(); column_ordered_it != mColumnsIndexed.end(); ++column_ordered_it)
{
- if ((*column_ordered_it)->getWidth() < 0)
+ LLScrollListColumn* column = *column_ordered_it;
+ if (!column || column->getWidth() < 0)
{
// skip hidden columns
continue;
}
- LLScrollListColumn* column = *column_ordered_it;
if (column->mHeader)
{
diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp
index 1fdd05a11c..bafeef41fb 100644
--- a/indra/llui/llsearcheditor.cpp
+++ b/indra/llui/llsearcheditor.cpp
@@ -34,7 +34,11 @@
LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
: LLUICtrl(p),
mSearchButton(NULL),
- mClearButton(NULL)
+ mClearButton(NULL),
+ mEditorImage(p.background_image),
+ mEditorImageFocused(p.background_image_focused),
+ mEditorSearchImage(p.background_image_highlight),
+ mHighlightTextField(p.highlight_text_field)
{
S32 srch_btn_top = p.search_button.top_pad + p.search_button.rect.height;
S32 srch_btn_right = p.search_button.rect.width + p.search_button.left_pad;
@@ -57,6 +61,8 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
// Set up line editor.
LLLineEditor::Params line_editor_params(p);
line_editor_params.name("filter edit box");
+ line_editor_params.background_image(p.background_image);
+ line_editor_params.background_image_focused(p.background_image_focused);
line_editor_params.rect(getLocalRect());
line_editor_params.follows.flags(FOLLOWS_ALL);
line_editor_params.text_pad_left(text_pad_left);
@@ -104,6 +110,20 @@ void LLSearchEditor::draw()
if (mClearButton)
mClearButton->setVisible(!mSearchEditor->getWText().empty());
+ if (mHighlightTextField)
+ {
+ if (!mSearchEditor->getWText().empty())
+ {
+ mSearchEditor->setBgImage(mEditorSearchImage);
+ mSearchEditor->setBgImageFocused(mEditorSearchImage);
+ }
+ else
+ {
+ mSearchEditor->setBgImage(mEditorImage);
+ mSearchEditor->setBgImageFocused(mEditorImageFocused);
+ }
+ }
+
LLUICtrl::draw();
}
diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h
index 3b12868225..c0f3c1d60c 100644
--- a/indra/llui/llsearcheditor.h
+++ b/indra/llui/llsearcheditor.h
@@ -47,14 +47,23 @@ public:
Optional<LLButton::Params> search_button,
clear_button;
Optional<bool> search_button_visible,
- clear_button_visible;
+ clear_button_visible,
+ highlight_text_field;
Optional<commit_callback_t> keystroke_callback;
+ Optional<LLUIImage*> background_image,
+ background_image_focused,
+ background_image_highlight;
+
Params()
: search_button("search_button"),
search_button_visible("search_button_visible"),
clear_button("clear_button"),
- clear_button_visible("clear_button_visible")
+ clear_button_visible("clear_button_visible"),
+ highlight_text_field("highlight_text_field"),
+ background_image("background_image"),
+ background_image_focused("background_image_focused"),
+ background_image_highlight("background_image_highlight")
{}
};
@@ -93,6 +102,13 @@ protected:
LLLineEditor* mSearchEditor;
LLButton* mSearchButton;
LLButton* mClearButton;
+
+ LLPointer<LLUIImage> mEditorImage;
+ LLPointer<LLUIImage> mEditorImageFocused;
+ LLPointer<LLUIImage> mEditorSearchImage;
+ LLPointer<LLUIImage> mEditorSearchImageFocused;
+
+ bool mHighlightTextField;
};
#endif // LL_SEARCHEDITOR_H
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index e5527da5cb..0aa7a2d217 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -38,6 +38,7 @@
#include "llrender.h"
#include "llfloater.h"
#include "lltrans.h"
+#include "lluiusage.h"
//----------------------------------------------------------------------------
@@ -1562,6 +1563,8 @@ BOOL LLTabContainer::setTab(S32 which)
if (is_selected)
{
+ LLUIUsage::instance().logPanel(tuple->mTabPanel->getName());
+
// Make sure selected tab is within scroll region
if (mIsVertical)
{
diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index e6f466ec78..5150df25f2 100644
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -967,6 +967,8 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id)
executeStopParam.function_name = executeStopFunction;
executeStopParam.parameter = commandp->executeStopParameters();
LLUICtrl::commit_callback_t execute_func = initCommitCallback(executeParam);
+ button->setFunctionName(commandp->executeFunctionName());
+ LL_DEBUGS("UIUsage") << "button function name a -> " << commandp->executeFunctionName() << LL_ENDL;
LLUICtrl::commit_callback_t stop_func = initCommitCallback(executeStopParam);
button->setMouseDownCallback(boost::bind(&LLToolBarButton::callIfEnabled, button, execute_func, _1, _2));
@@ -974,6 +976,8 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id)
}
else
{
+ button->setFunctionName(commandp->executeFunctionName());
+ LL_DEBUGS("UIUsage") << "button function name b -> " << commandp->executeFunctionName() << LL_ENDL;
button->setCommitCallback(executeParam);
}
@@ -1125,7 +1129,7 @@ BOOL LLToolBarButton::handleHover(S32 x, S32 y, MASK mask)
BOOL handled = FALSE;
S32 mouse_distance_squared = (x - mMouseDownX) * (x - mMouseDownX) + (y - mMouseDownY) * (y - mMouseDownY);
- S32 drag_threshold = LLUI::getInstance()->mSettingGroups["config"]->getS32("DragAndDropDistanceThreshold");
+ static LLCachedControl<S32> drag_threshold(*LLUI::getInstance()->mSettingGroups["config"], "DragAndDropDistanceThreshold", 3);
if (mouse_distance_squared > drag_threshold * drag_threshold
&& hasMouseCapture() &&
mStartDragItemCallback && mHandleDragItemCallback)
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 422534b781..2f56a8b1d0 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -358,8 +358,8 @@ void LLToolTip::draw()
if (mFadeTimer.getStarted())
{
- F32 tool_tip_fade_time = LLUI::getInstance()->mSettingGroups["config"]->getF32("ToolTipFadeTime");
- alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time, 1.f, 0.f);
+ static LLCachedControl<F32> tool_tip_fade_time(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipFadeTime", 0.2f);
+ alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time(), 1.f, 0.f);
if (alpha == 0.f)
{
// finished fading out, so hide ourselves
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 656b69d3ed..6f16745bd3 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -154,7 +154,6 @@ mAudioCallback(audio_callback),
mDeferredAudioCallback(deferred_audio_callback),
mWindow(NULL), // set later in startup
mRootView(NULL),
-mDirty(FALSE),
mHelpImpl(NULL)
{
LLRender2D::initParamSingleton(image_provider);
@@ -203,19 +202,6 @@ void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& rem
mClearPopupsFunc = clear_popups;
}
-void LLUI::dirtyRect(LLRect rect)
-{
- if (!mDirty)
- {
- mDirtyRect = rect;
- mDirty = TRUE;
- }
- else
- {
- mDirtyRect.unionWith(rect);
- }
-}
-
void LLUI::setMousePositionScreen(S32 x, S32 y)
{
#if defined(LL_DARWIN)
@@ -510,6 +496,18 @@ const LLView* LLUI::resolvePath(const LLView* context, const std::string& path)
return context;
}
+//static
+LLVector2& LLUI::getScaleFactor()
+{
+ return LLRender::sUIGLScaleFactor;
+}
+
+//static
+void LLUI::setScaleFactor(const LLVector2& scale_factor)
+{
+ LLRender::sUIGLScaleFactor = scale_factor;
+}
+
// LLLocalClipRect and LLScreenClipRect moved to lllocalcliprect.h/cpp
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 9856e551cc..30dbd7248f 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -245,10 +245,6 @@ public:
void setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t&, const clear_popups_t& );
- LLRect mDirtyRect;
- BOOL mDirty;
- void dirtyRect(LLRect rect);
-
// Return the ISO639 language name ("en", "ko", etc.) for the viewer UI.
// http://www.loc.gov/standards/iso639-2/php/code_list.php
std::string getUILanguage();
@@ -313,14 +309,14 @@ public:
void positionViewNearMouse(LLView* view, S32 spawn_x = S32_MAX, S32 spawn_y = S32_MAX);
// LLRender2D wrappers
- static void pushMatrix() { LLRender2D::getInstance()->pushMatrix(); }
- static void popMatrix() { LLRender2D::getInstance()->popMatrix(); }
- static void loadIdentity() { LLRender2D::getInstance()->loadIdentity(); }
- static void translate(F32 x, F32 y, F32 z = 0.0f) { LLRender2D::getInstance()->translate(x, y, z); }
-
- static LLVector2& getScaleFactor() { return LLRender2D::getInstance()->mGLScaleFactor; }
- static void setScaleFactor(const LLVector2& scale_factor) { LLRender2D::getInstance()->setScaleFactor(scale_factor); }
- static void setLineWidth(F32 width) { LLRender2D::getInstance()->setLineWidth(width); }
+ static void pushMatrix() { LLRender2D::pushMatrix(); }
+ static void popMatrix() { LLRender2D::popMatrix(); }
+ static void loadIdentity() { LLRender2D::loadIdentity(); }
+ static void translate(F32 x, F32 y, F32 z = 0.0f) { LLRender2D::translate(x, y, z); }
+
+ static LLVector2& getScaleFactor();
+ static void setScaleFactor(const LLVector2& scale_factor);
+ static void setLineWidth(F32 width) { LLRender2D::setLineWidth(width); }
static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0)
{ return LLRender2D::getInstance()->getUIImageByID(image_id, priority); }
static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0)
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 544a76e8d5..5924542a19 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -35,6 +35,7 @@
#include "lluictrlfactory.h"
#include "lltabcontainer.h"
#include "llaccordionctrltab.h"
+#include "lluiusage.h"
static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl");
@@ -282,6 +283,7 @@ LLUICtrl::commit_signal_t::slot_type LLUICtrl::initCommitCallback(const CommitCa
else
{
std::string function_name = cb.function_name;
+ setFunctionName(function_name);
commit_callback_t* func = (CommitCallbackRegistry::getValue(function_name));
if (func)
{
@@ -422,7 +424,19 @@ BOOL LLUICtrl::canFocusChildren() const
void LLUICtrl::onCommit()
{
if (mCommitSignal)
- (*mCommitSignal)(this, getValue());
+ {
+ if (!mFunctionName.empty())
+ {
+ LL_DEBUGS("UIUsage") << "calling commit function " << mFunctionName << LL_ENDL;
+ LLUIUsage::instance().logCommand(mFunctionName);
+ LLUIUsage::instance().logControl(getPathname());
+ }
+ else
+ {
+ //LL_DEBUGS("UIUsage") << "calling commit function " << "UNKNOWN" << LL_ENDL;
+ }
+ (*mCommitSignal)(this, getValue());
+ }
}
//virtual
@@ -597,6 +611,12 @@ void LLUICtrl::setMakeInvisibleControlVariable(LLControlVariable* control)
setVisible(!(mMakeInvisibleControlVariable->getValue().asBoolean()));
}
}
+
+void LLUICtrl::setFunctionName(const std::string& function_name)
+{
+ mFunctionName = function_name;
+}
+
// static
bool LLUICtrl::controlListener(const LLSD& newvalue, LLHandle<LLUICtrl> handle, std::string type)
{
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 7360bd7659..67dd24341c 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -183,6 +183,8 @@ public:
void setMakeVisibleControlVariable(LLControlVariable* control);
void setMakeInvisibleControlVariable(LLControlVariable* control);
+ void setFunctionName(const std::string& function_name);
+
virtual void setTentative(BOOL b);
virtual BOOL getTentative() const;
virtual void setValue(const LLSD& value);
@@ -310,6 +312,8 @@ protected:
LLControlVariable* mMakeInvisibleControlVariable;
boost::signals2::connection mMakeInvisibleControlConnection;
+ std::string mFunctionName;
+
static F32 sActiveControlTransparency;
static F32 sInactiveControlTransparency;
diff --git a/indra/llui/lluiusage.cpp b/indra/llui/lluiusage.cpp
new file mode 100644
index 0000000000..ccae6643b9
--- /dev/null
+++ b/indra/llui/lluiusage.cpp
@@ -0,0 +1,146 @@
+/**
+* @file lluiuisage.cpp
+* @brief Source file for LLUIUsage
+*
+* $LicenseInfo:firstyear=2021&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2021, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "linden_common.h"
+#include "lluiusage.h"
+#include <boost/algorithm/string.hpp>
+
+LLUIUsage::LLUIUsage()
+{
+}
+
+LLUIUsage::~LLUIUsage()
+{
+}
+
+// static
+std::string LLUIUsage::sanitized(const std::string& s)
+{
+ // Remove characters that make the ViewerStats db unhappy
+ std::string result(s);
+ std::replace(result.begin(), result.end(), '.', '_');
+ std::replace(result.begin(), result.end(), ' ', '_');
+ return result;
+}
+
+// static
+void LLUIUsage::setLLSDPath(LLSD& sd, const std::string& path, S32 max_elts, const LLSD& val)
+{
+ // Keep the last max_elts components of the specified path
+ std::vector<std::string> fields;
+ boost::split(fields, path, boost::is_any_of("/"));
+ auto first_pos = std::max(fields.begin(), fields.end() - max_elts);
+ auto end_pos = fields.end();
+ std::vector<std::string> last_fields(first_pos,end_pos);
+
+ setLLSDNested(sd, last_fields, val);
+}
+
+// setLLSDNested()
+// Accomplish the equivalent of
+// sd[fields[0]][fields[1]]... = val;
+// for an arbitrary number of fields.
+// This might be useful as an LLSD utility function; is not specific to LLUIUsage
+//
+// static
+void LLUIUsage::setLLSDNested(LLSD& sd, const std::vector<std::string>& fields, const LLSD& val)
+{
+ LLSD* fsd = &sd;
+ for (auto it=fields.begin(); it!=fields.end(); ++it)
+ {
+ if (it == fields.end()-1)
+ {
+ (*fsd)[*it] = val;
+ }
+ else
+ {
+ if (!(*fsd)[*it].isMap())
+ {
+ (*fsd)[*it] = LLSD::emptyMap();
+ }
+ fsd = &(*fsd)[*it];
+ }
+ }
+}
+
+void LLUIUsage::logCommand(const std::string& command)
+{
+ mCommandCounts[sanitized(command)]++;
+ LL_DEBUGS("UIUsage") << "command " << command << LL_ENDL;
+}
+
+void LLUIUsage::logControl(const std::string& control)
+{
+ mControlCounts[sanitized(control)]++;
+ LL_DEBUGS("UIUsage") << "control " << control << LL_ENDL;
+}
+
+
+void LLUIUsage::logFloater(const std::string& floater)
+{
+ mFloaterCounts[sanitized(floater)]++;
+ LL_DEBUGS("UIUsage") << "floater " << floater << LL_ENDL;
+}
+
+void LLUIUsage::logPanel(const std::string& p)
+{
+ mPanelCounts[sanitized(p)]++;
+ LL_DEBUGS("UIUsage") << "panel " << p << LL_ENDL;
+}
+
+LLSD LLUIUsage::asLLSD() const
+{
+ LLSD result;
+ for (auto const& it : mCommandCounts)
+ {
+ result["commands"][it.first] = LLSD::Integer(it.second);
+ }
+ for (auto const& it : mControlCounts)
+ {
+ setLLSDPath(result["controls"], it.first, 2, LLSD::Integer(it.second));
+ }
+ for (auto const& it : mFloaterCounts)
+ {
+ result["floaters"][it.first] = LLSD::Integer(it.second);
+ }
+ for (auto const& it : mPanelCounts)
+ {
+ result["panels"][it.first] = LLSD::Integer(it.second);
+ }
+ return result;
+}
+
+// Clear up some junk content generated during initial login/UI initialization
+void LLUIUsage::clear()
+{
+
+ LL_DEBUGS("UIUsage") << "clear" << LL_ENDL;
+ mCommandCounts.clear();
+ mControlCounts.clear();
+ mFloaterCounts.clear();
+ mPanelCounts.clear();
+}
+
diff --git a/indra/llui/lluiusage.h b/indra/llui/lluiusage.h
new file mode 100644
index 0000000000..a30cd80db3
--- /dev/null
+++ b/indra/llui/lluiusage.h
@@ -0,0 +1,57 @@
+/**
+* @file lluiuisage.h
+* @brief Header file for LLUIUsage
+*
+* $LicenseInfo:firstyear=2021&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2021, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLUIUSAGE_H
+#define LL_LLUIUSAGE_H
+
+#include <map>
+#include "llsd.h"
+#include "llsingleton.h"
+
+// UIUsage tracking to see which operations and UI elements are most popular in a session
+class LLUIUsage : public LLSingleton<LLUIUsage>
+{
+public:
+ LLSINGLETON(LLUIUsage);
+ ~LLUIUsage();
+public:
+ static std::string sanitized(const std::string& s);
+ static void setLLSDPath(LLSD& sd, const std::string& path, S32 max_elts, const LLSD& val);
+ static void setLLSDNested(LLSD& sd, const std::vector<std::string>& fields, const LLSD& val);
+ void logCommand(const std::string& command);
+ void logControl(const std::string& control);
+ void logFloater(const std::string& floater);
+ void logPanel(const std::string& p);
+ LLSD asLLSD() const;
+ void clear();
+private:
+ std::map<std::string,U32> mCommandCounts;
+ std::map<std::string,U32> mControlCounts;
+ std::map<std::string,U32> mFloaterCounts;
+ std::map<std::string,U32> mPanelCounts;
+};
+
+#endif // LLUIUIUSAGE.h
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 20dda54771..e43c52c0c2 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -176,7 +176,7 @@ void LLUrlEntryBase::callObservers(const std::string &id,
bool LLUrlEntryBase::isLinkDisabled() const
{
// this allows us to have a global setting to turn off text hyperlink highlighting/action
- bool globally_disabled = LLUI::getInstance()->mSettingGroups["config"]->getBOOL("DisableTextHyperlinkActions");
+ static LLCachedControl<bool> globally_disabled(*LLUI::getInstance()->mSettingGroups["config"], "DisableTextHyperlinkActions", false);
return globally_disabled;
}
@@ -464,7 +464,9 @@ LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL()
"|"
"(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?)"
"|"
- "(https://([-\\w\\.]*\\.)?secondlifegrid\\.net(:\\d{1,5})?))"
+ "(https://([-\\w\\.]*\\.)?secondlifegrid\\.net(:\\d{1,5})?)"
+ "|"
+ "(https?://([-\\w\\.]*\\.)?secondlife\\.io(:\\d{1,5})?))"
"\\/\\S*",
boost::regex::perl|boost::regex::icase);
@@ -1127,7 +1129,7 @@ std::string LLUrlEntryPlace::getLocation(const std::string &url) const
//
LLUrlEntryRegion::LLUrlEntryRegion()
{
- mPattern = boost::regex("secondlife:///app/region/[^/\\s]+(/\\d+)?(/\\d+)?(/\\d+)?/?",
+ mPattern = boost::regex("secondlife:///app/region/[A-Za-z0-9()_%]+(/\\d+)?(/\\d+)?(/\\d+)?/?",
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_slurl.xml";
mTooltip = LLTrans::getString("TooltipSLURL");
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index cd47e2ecea..b942be2a4a 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -60,6 +60,8 @@ static const S32 LINE_HEIGHT = 15;
S32 LLView::sDepth = 0;
bool LLView::sDebugRects = false;
+bool LLView::sIsRectDirty = false;
+LLRect LLView::sDirtyRect;
bool LLView::sDebugRectsShowNames = true;
bool LLView::sDebugKeys = false;
bool LLView::sDebugMouseHandling = false;
@@ -885,14 +887,16 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
std::string tooltip = getToolTip();
if (!tooltip.empty())
{
+ static LLCachedControl<F32> tooltip_fast_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipFastDelay", 0.1f);
+ static LLCachedControl<F32> tooltip_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipDelay", 0.7f);
+ static LLCachedControl<bool> allow_ui_tooltips(*LLUI::getInstance()->mSettingGroups["config"], "BasicUITooltips", true);
// allow "scrubbing" over ui by showing next tooltip immediately
// if previous one was still visible
F32 timeout = LLToolTipMgr::instance().toolTipVisible()
- ? LLUI::getInstance()->mSettingGroups["config"]->getF32( "ToolTipFastDelay" )
- : LLUI::getInstance()->mSettingGroups["config"]->getF32( "ToolTipDelay" );
+ ? tooltip_fast_delay
+ : tooltip_delay;
// Even if we don't show tooltips, consume the event, nothing below should show tooltip
- bool allow_ui_tooltips = LLUI::getInstance()->mSettingGroups["config"]->getBOOL("BasicUITooltips");
if (allow_ui_tooltips)
{
LLToolTipMgr::instance().show(LLToolTip::Params()
@@ -1189,7 +1193,7 @@ void LLView::drawChildren()
if (viewp->getVisible() && viewp->getRect().isValid())
{
LLRect screen_rect = viewp->calcScreenRect();
- if ( rootp->getLocalRect().overlaps(screen_rect) && LLUI::getInstance()->mDirtyRect.overlaps(screen_rect))
+ if ( rootp->getLocalRect().overlaps(screen_rect) && sDirtyRect.overlaps(screen_rect))
{
LLUI::pushMatrix();
{
@@ -1231,7 +1235,15 @@ void LLView::dirtyRect()
parent = parent->getParent();
}
- LLUI::getInstance()->dirtyRect(cur->calcScreenRect());
+ if (!sIsRectDirty)
+ {
+ sDirtyRect = cur->calcScreenRect();
+ sIsRectDirty = true;
+ }
+ else
+ {
+ sDirtyRect.unionWith(cur->calcScreenRect());
+ }
}
//Draw a box for debugging.
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 5c91c37d3c..c60dcf3344 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -657,6 +657,9 @@ public:
// Draw debug rectangles around widgets to help with alignment and spacing
static bool sDebugRects;
+ static bool sIsRectDirty;
+ static LLRect sDirtyRect;
+
// Draw widget names and sizes when drawing debug rectangles, turning this
// off is useful to make the rectangles themselves easier to see.
static bool sDebugRectsShowNames;
diff --git a/indra/llui/llvirtualtrackball.cpp b/indra/llui/llvirtualtrackball.cpp
index 723643dd25..6e0aef740d 100644
--- a/indra/llui/llvirtualtrackball.cpp
+++ b/indra/llui/llvirtualtrackball.cpp
@@ -348,6 +348,42 @@ LLQuaternion LLVirtualTrackball::getRotation() const
return mValue;
}
+// static
+void LLVirtualTrackball::getAzimuthAndElevation(const LLQuaternion &quat, F32 &azimuth, F32 &elevation)
+{
+ // LLQuaternion has own function to get azimuth, but it doesn't appear to return correct values (meant for 2d?)
+ LLVector3 point = VectorZero * quat;
+
+ if (!is_approx_zero(point.mV[VX]) || !is_approx_zero(point.mV[VY]))
+ {
+ azimuth = atan2f(point.mV[VX], point.mV[VY]);
+ }
+ else
+ {
+ azimuth = 0;
+ }
+
+ azimuth -= F_PI_BY_TWO;
+
+ if (azimuth < 0)
+ {
+ azimuth += F_PI * 2;
+ }
+
+ // while vector is '1', F32 is not sufficiently precise and we can get
+ // values like 1.0000012 which will result in -90deg angle instead of 90deg
+ F32 z = llclamp(point.mV[VZ], -1.f, 1.f);
+ elevation = asin(z); // because VectorZero's length is '1'
+}
+
+// static
+void LLVirtualTrackball::getAzimuthAndElevationDeg(const LLQuaternion &quat, F32 &azimuth, F32 &elevation)
+{
+ getAzimuthAndElevation(quat, azimuth, elevation);
+ azimuth *= RAD_TO_DEG;
+ elevation *= RAD_TO_DEG;
+}
+
BOOL LLVirtualTrackball::handleHover(S32 x, S32 y, MASK mask)
{
if (hasMouseCapture())
@@ -409,6 +445,10 @@ BOOL LLVirtualTrackball::handleHover(S32 x, S32 y, MASK mask)
mValue *= az_quat;
}
+ // we are doing a lot of F32 mathematical operations with loss of precision,
+ // re-normalize to compensate
+ mValue.normalize();
+
mPrevX = x;
mPrevY = y;
onCommit();
diff --git a/indra/llui/llvirtualtrackball.h b/indra/llui/llvirtualtrackball.h
index 2d4b1ece17..c7a893877b 100644
--- a/indra/llui/llvirtualtrackball.h
+++ b/indra/llui/llvirtualtrackball.h
@@ -96,6 +96,9 @@ public:
void setRotation(const LLQuaternion &value);
LLQuaternion getRotation() const;
+ static void getAzimuthAndElevation(const LLQuaternion &quat, F32 &azimuth, F32 &elevation);
+ static void getAzimuthAndElevationDeg(const LLQuaternion &quat, F32 &azimuth, F32 &elevation);
+
protected:
friend class LLUICtrlFactory;
LLVirtualTrackball(const Params&);
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 4a4fdb72e3..1a474cca90 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -739,11 +739,6 @@ namespace tut
"XXX secondlife:///app/region/Burning%20Life%20(Hyper)/27/210/30 XXX",
"secondlife:///app/region/Burning%20Life%20(Hyper)/27/210/30");
- // DEV-35459: SLURLs and teleport Links not parsed properly
- testRegex("Region with quote", url,
- "XXX secondlife:///app/region/A'ksha%20Oasis/41/166/701 XXX",
- "secondlife:///app/region/A%27ksha%20Oasis/41/166/701");
-
// Rendering tests.
testLabel("Render /app/region/Ahern/50/50/50/", url,
"secondlife:///app/region/Ahern/50/50/50/",